Download plugins/CustomDimensions/API.php from Leon4gr45/matomo: direct link, hf CLI and curl.
- Browser
- Download file 14 kB
-
https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/plugins/CustomDimensions/API.php
- Command line
-
hf download hf://spaces/Leon4gr45/matomo/plugins/CustomDimensions/API.php
-
curl -L -o API.php https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/plugins/CustomDimensions/API.php
14 kB
| /** | |
| * Matomo - free/libre analytics platform | |
| * | |
| * @link https://matomo.org | |
| * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | |
| */ | |
| namespace Piwik\Plugins\CustomDimensions; | |
| use Piwik\Common; | |
| use Piwik\Archive; | |
| use Piwik\DataTable; | |
| use Piwik\Filesystem; | |
| use Piwik\Piwik; | |
| use Piwik\Plugins\CustomDimensions\Dao\Configuration; | |
| use Piwik\Plugins\CustomDimensions\Dao\LogTable; | |
| use Piwik\Plugins\CustomDimensions\Dimension\Active; | |
| use Piwik\Plugins\CustomDimensions\Dimension\CaseSensitive; | |
| use Piwik\Plugins\CustomDimensions\Dimension\Description; | |
| use Piwik\Plugins\CustomDimensions\Dimension\Dimension; | |
| use Piwik\Plugins\CustomDimensions\Dimension\Extraction; | |
| use Piwik\Plugins\CustomDimensions\Dimension\Extractions; | |
| use Piwik\Plugins\CustomDimensions\Dimension\Index; | |
| use Piwik\Plugins\CustomDimensions\Dimension\Name; | |
| use Piwik\Plugins\CustomDimensions\Dimension\Scope; | |
| use Piwik\Tracker\Cache; | |
| /** | |
| * The Custom Dimensions API lets you manage and access reports for your configured Custom Dimensions. | |
| * | |
| * @method static API getInstance() | |
| */ | |
| class API extends \Piwik\Plugin\API | |
| { | |
| /** | |
| * Returns the report for a configured custom dimension. Only reports for active dimensions can be fetched. | |
| * | |
| * @param int $idDimension Custom dimension ID to load the report for. | |
| * @param int $idSite The numeric ID of the website to query. | |
| * @param 'day'|'week'|'month'|'year'|'range' $period The period to process, processes data for the period | |
| * containing the specified date. | |
| * @param string $date The date or date range to process. | |
| * 'YYYY-MM-DD', magic keywords (today, yesterday, lastWeek, lastMonth, lastYear), | |
| * or date range (ie, 'YYYY-MM-DD,YYYY-MM-DD', lastX, previousX). | |
| * @param string|null|false $segment Custom segment to filter the report. | |
| * Example: "referrerName==example.com" | |
| * Supports AND (;) and OR (,) operators. | |
| * @param bool $expanded Whether subtables should be expanded in the response. | |
| * @param bool $flat Whether subtable rows should be flattened into a single table. | |
| * @param int|false $idSubtable Optional subtable ID to load. | |
| * @return DataTable|DataTable\Map | |
| */ | |
| public function getCustomDimension(int $idDimension, int $idSite, string $period, string $date, $segment = false, bool $expanded = false, bool $flat = false, $idSubtable = false) | |
| { | |
| Piwik::checkUserHasViewAccess($idSite); | |
| $dimension = new Dimension($idDimension, $idSite); | |
| $dimension->checkActive(); | |
| $record = Archiver::buildRecordNameForCustomDimensionId($idDimension); | |
| $dataTable = Archive::createDataTableFromArchive($record, $idSite, $period, $date, $segment ?: '', $expanded, $flat, $idSubtable); | |
| if (!empty($idSubtable) && $dataTable->getRowsCount()) { | |
| $parentTable = Archive::createDataTableFromArchive($record, $idSite, $period, $date, $segment ?: ''); | |
| $row = $parentTable->getRowFromIdSubDataTable($idSubtable); | |
| if ($row) { | |
| $parentValue = $row->getColumn('label'); | |
| $dataTable->filter('Piwik\Plugins\CustomDimensions\DataTable\Filter\AddSubtableSegmentMetadata', array($idDimension, $parentValue)); | |
| } | |
| } else { | |
| $dataTable->filter('Piwik\Plugins\CustomDimensions\DataTable\Filter\AddSegmentMetadata', array($idDimension)); | |
| } | |
| $dataTable->filter('Piwik\Plugins\CustomDimensions\DataTable\Filter\RemoveUserIfNeeded', array($idSite, $period, $date)); | |
| return $dataTable; | |
| } | |
| /** | |
| * Configures a new custom dimension for a site. Note that custom dimensions cannot be deleted, so be careful | |
| * when creating one as you might run out of available custom dimension slots. | |
| * | |
| * A current list of available scopes can be fetched via `CustomDimensions.getAvailableScopes`. That method | |
| * also indicates whether custom dimension slots are still available or all in use. | |
| * | |
| * @param int $idSite The numeric ID of the website to configure the dimension for. | |
| * @param string $name The custom dimension name. | |
| * @param 'visit'|'action' $scope The dimension scope. Use `CustomDimensions.getAvailableScopes` for an | |
| * up-to-date list. | |
| * @param bool|int $active Whether the custom dimension should be active. | |
| * @param array<int, array{dimension:string, pattern:string}> $extractions Optional extraction rules, e.g. | |
| * `[{"dimension": "url", "pattern": "index_(.+).html"}, {"dimension": "urlparam", "pattern": "..."}]`. | |
| * Supported dimensions include `url`, `urlparam`, and `action_name`. Use | |
| * `CustomDimensions.getAvailableExtractionDimensions` for the full list. | |
| * Extractions are supported only for the `action` scope. | |
| * @param bool|int $caseSensitive Whether extraction matching should be case-sensitive. | |
| * @param string $description Optional description to provide additional context for the custom dimension. | |
| * @return int ID of the configured custom dimension. Note that the same ID may be used for different websites. | |
| */ | |
| public function configureNewCustomDimension(int $idSite, string $name, string $scope, $active, $extractions = [], $caseSensitive = true, string $description = '') | |
| { | |
| Piwik::checkUserHasWriteAccess($idSite); | |
| $this->checkCustomDimensionConfig($name, $active, $extractions, $caseSensitive, $description); | |
| $scopeCheck = new Scope($scope); | |
| $scopeCheck->check(); | |
| $extractions = $this->unsanitizeExtractions($extractions); | |
| $this->checkExtractionsAreSupportedForScope($scope, $extractions); | |
| $index = new Index(); | |
| $index = $index->getNextIndex($idSite, $scope); | |
| $configuration = $this->getConfiguration(); | |
| $idDimension = $configuration->configureNewDimension($idSite, $name, $scope, $index, $active, $extractions, $caseSensitive, $description); | |
| Cache::deleteCacheWebsiteAttributes($idSite); | |
| Cache::clearCacheGeneral(); | |
| Filesystem::deleteAllCacheOnUpdate(); | |
| return $idDimension; | |
| } | |
| /** | |
| * @param array<int, array{dimension?:mixed, pattern?:mixed}> $extractions | |
| * @return array<int, array{dimension?:mixed, pattern?:mixed}> | |
| */ | |
| private function unsanitizeExtractions($extractions) | |
| { | |
| if (!empty($extractions) && is_array($extractions)) { | |
| foreach ($extractions as $index => $extraction) { | |
| if (!empty($extraction['pattern']) && is_string($extraction['pattern'])) { | |
| $extractions[$index]['pattern'] = Common::unsanitizeInputValue($extraction['pattern']); | |
| } | |
| } | |
| } | |
| return $extractions; | |
| } | |
| /** | |
| * Updates an existing custom dimension. This method updates all values, so you need to pass existing values | |
| * of the dimension if you do not want to reset any value. | |
| * | |
| * @param int $idDimension Custom dimension ID to update. | |
| * @param int $idSite The numeric ID of the website the dimension belongs to. | |
| * @param string $name The custom dimension name. | |
| * @param bool|int $active Whether the custom dimension should be active. | |
| * @param array<int, array{dimension:string, pattern:string}> $extractions Optional extraction rules, e.g. | |
| * `[{"dimension": "url", "pattern": "index_(.+).html"}, {"dimension": "urlparam", "pattern": "..."}]`. | |
| * Supported dimensions include `url`, `urlparam`, and `action_name`. Use | |
| * `CustomDimensions.getAvailableExtractionDimensions` for the full list. | |
| * Extractions are supported only for the `action` scope. | |
| * @param bool|int|null $caseSensitive Whether extraction matching should be case-sensitive. | |
| * Use `null` to keep the current setting. | |
| * @param string|null $description Optional description to provide additional context for the custom dimension. | |
| * Use `null` to keep the current description. | |
| */ | |
| public function configureExistingCustomDimension(int $idDimension, int $idSite, string $name, $active, $extractions = [], $caseSensitive = null, ?string $description = null): void | |
| { | |
| Piwik::checkUserHasWriteAccess($idSite); | |
| $dimension = new Dimension($idDimension, $idSite); | |
| $dimension->checkExists(); | |
| if (!isset($caseSensitive)) { | |
| $caseSensitive = $dimension->getCaseSensitive(); | |
| } | |
| if (!isset($description)) { | |
| $description = $dimension->getDescription(); | |
| } | |
| $extractions = $this->unsanitizeExtractions($extractions); | |
| $this->checkCustomDimensionConfig($name, $active, $extractions, $caseSensitive, $description); | |
| $this->checkExtractionsAreSupportedForScope($dimension->getScope(), $extractions); | |
| $this->getConfiguration()->configureExistingDimension($idDimension, $idSite, $name, $active, $extractions, $caseSensitive, $description); | |
| Cache::deleteCacheWebsiteAttributes($idSite); | |
| Cache::clearCacheGeneral(); | |
| } | |
| /** | |
| * @param string $scope | |
| * @param array<int, array{dimension:string, pattern:string}> $extractions | |
| */ | |
| private function checkExtractionsAreSupportedForScope($scope, $extractions): void | |
| { | |
| if (!CustomDimensions::doesScopeSupportExtractions($scope) && !empty($extractions)) { | |
| throw new \Exception("Extractions can be used only in scope 'action'"); | |
| } | |
| } | |
| /** | |
| * Returns all configured custom dimensions for a site. | |
| * | |
| * @param int $idSite The numeric ID of the website to query. | |
| * @return array<int, array<string, mixed>> | |
| */ | |
| public function getConfiguredCustomDimensions(int $idSite) | |
| { | |
| Piwik::checkUserHasViewAccess($idSite); | |
| return $this->getConfiguration()->getCustomDimensionsForSite($idSite); | |
| } | |
| /** | |
| * For convenience. Hidden to reduce API surface area. | |
| * | |
| * @param int $idSite The numeric ID of the website to query. | |
| * @param string $scope Scope to filter configured dimensions by. | |
| * @return array<int, array<string, mixed>> | |
| * @hide | |
| */ | |
| public function getConfiguredCustomDimensionsHavingScope(int $idSite, $scope) | |
| { | |
| $result = $this->getConfiguredCustomDimensions($idSite); | |
| $result = array_filter($result, function ($row) use ($scope) { | |
| return $row['scope'] == $scope; | |
| }); | |
| return array_values($result); | |
| } | |
| /** | |
| * @param bool|int $active | |
| * @param array<int, array{dimension:string, pattern:string}> $extractions | |
| * @param bool|int|null $caseSensitive | |
| */ | |
| private function checkCustomDimensionConfig(string $name, $active, $extractions, $caseSensitive, string $description = ''): void | |
| { | |
| // ideally we would work with these objects a bit more instead of arrays but we'd have a lot of | |
| // serialize/unserialize to do as we need to cache all configured custom dimensions for tracker cache and | |
| // we do not want to serialize all php instances there. Also we need to return an array for each | |
| // configured dimension in API methods anyway | |
| $name = new Name($name); | |
| $name->check(); | |
| $active = new Active($active); | |
| $active->check(); | |
| $extractions = new Extractions($extractions); | |
| $extractions->check(); | |
| $caseSensitive = new CaseSensitive($caseSensitive); | |
| $caseSensitive->check(); | |
| $description = new Description($description); | |
| $description->check(); | |
| } | |
| /** | |
| * Returns the supported custom-dimension scopes for a site. The response also contains information about | |
| * how many custom dimension slots are available, used, and remaining, which can be used to check whether | |
| * more custom dimensions can be created via `CustomDimensions.configureNewCustomDimension`. | |
| * | |
| * @param int $idSite The numeric ID of the website to query. | |
| * @return array<int, array{value:string, name:string, numSlotsAvailable:int, numSlotsUsed:int, numSlotsLeft:int, supportsExtractions:bool}> | |
| */ | |
| public function getAvailableScopes(int $idSite): array | |
| { | |
| Piwik::checkUserHasViewAccess($idSite); | |
| $scopes = []; | |
| foreach (CustomDimensions::getPublicScopes() as $scope) { | |
| $configs = $this->getConfiguredCustomDimensionsHavingScope($idSite, $scope); | |
| $indexes = $this->getTracking($scope)->getInstalledIndexes(); | |
| $scopes[] = [ | |
| 'value' => $scope, | |
| 'name' => Piwik::translate('General_TrackingScope' . ucfirst($scope)), | |
| 'numSlotsAvailable' => count($indexes), | |
| 'numSlotsUsed' => count($configs), | |
| 'numSlotsLeft' => count($indexes) - count($configs), | |
| 'supportsExtractions' => CustomDimensions::doesScopeSupportExtractions($scope), | |
| ]; | |
| } | |
| return $scopes; | |
| } | |
| /** | |
| * Returns the dimensions that can be used in extraction rules. | |
| * | |
| * @return array<int, array{value:string, name:string}> | |
| */ | |
| public function getAvailableExtractionDimensions(): array | |
| { | |
| Piwik::checkUserHasSomeWriteAccess(); | |
| $supported = Extraction::getSupportedDimensions(); | |
| $dimensions = []; | |
| foreach ($supported as $value => $dimension) { | |
| $dimensions[] = ['value' => $value, 'name' => $dimension]; | |
| } | |
| return $dimensions; | |
| } | |
| private function getTracking(string $scope): LogTable | |
| { | |
| return new LogTable($scope); | |
| } | |
| private function getConfiguration(): Configuration | |
| { | |
| return new Configuration(); | |
| } | |
| } | |