File: /var/www/html/wp-content/plugins/matomo/app/core/Policy/PolicyManager.php
<?php
/**
* 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\Policy;
use Exception;
use Piwik\Tracker\Cache;
use Piwik\Plugin\Manager;
use Piwik\Policy\Exceptions\CompliancePolicyNotFoundException;
use Piwik\Settings\Interfaces\PolicyComparisonInterface;
use Piwik\Settings\Interfaces\SettingValueInterface;
use Piwik\Settings\Interfaces\Traits\Getters\ConfigGetterTrait;
use Piwik\Settings\Interfaces\Traits\Getters\CustomGetterTrait;
use Piwik\Settings\Interfaces\Traits\Getters\MeasurableGetterTrait;
use Piwik\Settings\Interfaces\Traits\Getters\OptionGetterTrait;
use Piwik\Settings\Interfaces\Traits\Getters\SystemGetterTrait;
use Piwik\Settings\Measurable\MeasurableProperty;
use Piwik\Settings\Measurable\MeasurableSetting;
use Piwik\Settings\Plugin\SystemConfigSetting;
use Piwik\Settings\Plugin\SystemSetting;
use Piwik\Settings\Setting;
use Piwik\Tracker\Config\ThirdPartyCookies;
class PolicyManager
{
public const SETTING_TYPE_SYSTEM = 'system';
public const SETTING_TYPE_MEASURABLE = 'measurable';
public const SETTING_TYPE_CUSTOM = 'custom';
public const SETTING_TYPE_OPTION = 'option';
public const SETTING_TYPE_CONFIG = 'config';
// TODO: In Matomo 6, get*Name methods will change visibility from protected to public,
// so we will need to replace the method names here
private static $settingTypesMap = [self::SETTING_TYPE_SYSTEM => ['trait' => SystemGetterTrait::class, 'method' => 'getSystemSettingShortName'], self::SETTING_TYPE_MEASURABLE => ['trait' => MeasurableGetterTrait::class, 'method' => 'getMeasurableSettingShortName'], self::SETTING_TYPE_CUSTOM => ['trait' => CustomGetterTrait::class, 'method' => 'getCustomSettingShortName'], self::SETTING_TYPE_OPTION => ['trait' => OptionGetterTrait::class, 'method' => 'getOptionSettingShortName'], self::SETTING_TYPE_CONFIG => ['trait' => ConfigGetterTrait::class, 'method' => 'getConfigSettingShortName']];
/**
* @return array<class-string<CompliancePolicy>>
*/
public static function getAllPolicies() : array
{
return [\Piwik\Policy\CnilPolicy::class];
}
/**
* @return array<array<string, string>>
*/
public static function getAllPoliciesDetails() : array
{
$policies = static::getAllPolicies();
return array_map(function ($policyClass) {
return $policyClass::getDetails();
}, $policies);
}
/**
* @return class-string<CompliancePolicy>|null
*/
public static function getPolicyByName(string $policyName) : ?string
{
$policies = static::getAllPolicies();
foreach ($policies as $policyClass) {
if ($policyName === $policyClass::getName()) {
return $policyClass;
}
}
return null;
}
/**
* @return array<class-string<PolicyComparisonInterface<mixed>&SettingValueInterface<mixed>>>
*/
protected static function getAllSettings(?string $settingType = null) : array
{
$settings = Manager::getInstance()->findMultipleComponents('Settings', SettingValueInterface::class);
$underPolicy = [];
// Add core specific settings
$settings[] = ThirdPartyCookies::class;
foreach ($settings as $setting) {
if (!is_a($setting, PolicyComparisonInterface::class, \true)) {
continue;
}
if ($settingType && !in_array(self::$settingTypesMap[$settingType]['trait'], class_uses($setting), \true)) {
continue;
}
$underPolicy[] = $setting;
}
return $underPolicy;
}
/**
* @param class-string<CompliancePolicy> $policyClass
* @return array<class-string<PolicyComparisonInterface<mixed>&SettingValueInterface<mixed>>>
*/
public static function getAllControlledSettings(string $policyClass, ?int $idSite = null, ?string $settingType = null) : array
{
$settings = static::getAllSettings($settingType);
$underPolicy = [];
foreach ($settings as $setting) {
if (!$setting::isControlledBySpecificPolicy($policyClass, $idSite)) {
continue;
}
$underPolicy[] = $setting;
}
return $underPolicy;
}
/**
* @param class-string<CompliancePolicy> $policyClass
* @throws CompliancePolicyNotFoundException when $policyClass is not a valid policy
*/
public static function isPolicyActive(string $policyClass, ?int $idSite = null) : bool
{
self::checkPolicyIsValid($policyClass);
return $policyClass::isActive($idSite);
}
/**
* @param class-string<CompliancePolicy> $policyClass
* @throws \Exception when $policyClass is not a valid policy
*/
public static function isPolicyConfigControlled(string $policyClass) : bool
{
self::checkPolicyIsValid($policyClass);
return $policyClass::isConfigControlled();
}
/**
* @param class-string<CompliancePolicy> $policyClass
* @return array<array<string>> of [['title' => (string) 'TITLE', 'note' => (string) 'NOTE']]
* @throws CompliancePolicyNotFoundException when $policyClass is not a valid policy
*/
public static function getAllUnknownSettings(string $policyClass) : array
{
self::checkPolicyIsValid($policyClass);
return $policyClass::getUnknownSettings();
}
/**
* @param class-string<CompliancePolicy> $policyClass
* @throws CompliancePolicyNotFoundException when $policyClass is not a valid policy
*/
private static function checkPolicyIsValid(string $policyClass) : void
{
if (!is_a($policyClass, \Piwik\Policy\CompliancePolicy::class, \true)) {
throw new CompliancePolicyNotFoundException('Invalid compliance policy.');
}
}
/**
* @param class-string<CompliancePolicy> $policyClass
* @throws CompliancePolicyNotFoundException when $policyClass is not a valid policy
*/
public static function setPolicyActiveStatus(string $policyClass, bool $isActive, ?int $idSite = null) : void
{
self::checkPolicyIsValid($policyClass);
$policyClass::setActiveStatus($idSite, $isActive);
if (!is_null($idSite)) {
Cache::deleteCacheWebsiteAttributes($idSite);
}
Cache::deleteTrackerCache();
}
public static function storePolicySettingValuesInTrackerCache(array &$cacheContent, int $idSite) : array
{
$settings = static::getAllSettings();
foreach ($settings as $setting) {
$cacheContent[$setting] = $setting::getInstance($idSite)->getValue();
}
return $cacheContent;
}
/**
* Return setting type from a given Setting instance, including subclasses
*/
public static function getSettingTypeFromSettingClass(Setting $setting) : ?string
{
$map = [MeasurableSetting::class => self::SETTING_TYPE_MEASURABLE, MeasurableProperty::class => self::SETTING_TYPE_MEASURABLE, SystemSetting::class => self::SETTING_TYPE_SYSTEM, SystemConfigSetting::class => self::SETTING_TYPE_CONFIG];
foreach ($map as $class => $type) {
if ($setting instanceof $class) {
return $type;
}
}
return null;
}
/**
* For a given setting name, return an information on policies that may control the setting and its required value.
*
* @return array<string, array{
* requiredValue: mixed
* }>
* @throws Exception
*/
public static function getCompliancePoliciesControllingASetting(string $settingName, ?int $idSite = null, ?string $settingType = null) : array
{
if (!$settingType || !in_array($settingType, array_keys(self::$settingTypesMap), \true)) {
return [];
}
$policies = static::getAllPolicies();
$settings = [];
foreach ($policies as $policyClass) {
if (\false === $policyClass::isActive($idSite)) {
continue;
}
$controlledSettings = self::getAllControlledSettings($policyClass, $idSite, $settingType);
foreach ($controlledSettings as $controlledSetting) {
if ($settingName === call_user_func([$controlledSetting, self::$settingTypesMap[$settingType]['method']])) {
$settings[$policyClass::getName()] = ['requiredValue' => $controlledSetting::getPolicyRequirements()[$policyClass]];
}
}
}
return $settings;
}
}