<?php

namespace MatthiasWeb\RealMediaLibrary\Vendor\DevOwl\RealProductManagerWpClient\license;

use MatthiasWeb\RealMediaLibrary\Vendor\DevOwl\RealProductManagerWpClient\client\ClientUtils;
use MatthiasWeb\RealMediaLibrary\Vendor\DevOwl\RealProductManagerWpClient\Core;
use MatthiasWeb\RealMediaLibrary\Vendor\DevOwl\RealProductManagerWpClient\PluginUpdate;
use MatthiasWeb\RealMediaLibrary\Vendor\DevOwl\RealProductManagerWpClient\Utils;
use MatthiasWeb\RealMediaLibrary\Vendor\DevOwl\RealProductManagerWpClient\UtilsProvider;
use WP_Error;
// @codeCoverageIgnoreStart
\defined('ABSPATH') or die('No script kiddies please!');
// Avoid direct file request
// @codeCoverageIgnoreEnd
/**
 * Handle license information for a given plugin and associated blog id.
 * @internal
 */
class License
{
    use UtilsProvider;
    const OPTION_NAME_CODE_PREFIX = RPM_WP_CLIENT_OPT_PREFIX . '-code_';
    const OPTION_NAME_UUID_PREFIX = RPM_WP_CLIENT_OPT_PREFIX . '-uuid_';
    const OPTION_NAME_HOST_NAME = RPM_WP_CLIENT_OPT_PREFIX . '-hostname_';
    const OPTION_NAME_TELEMETRY_PREFIX = RPM_WP_CLIENT_OPT_PREFIX . '-telemetry_';
    const OPTION_NAME_INSTALLATION_TYPE_PREFIX = RPM_WP_CLIENT_OPT_PREFIX . '-installationType_';
    const OPTION_NAME_HINT_PREFIX = RPM_WP_CLIENT_OPT_PREFIX . '-hint_';
    const OPTION_NAME_LICENSE_ACTIVATION_PREFIX = RPM_WP_CLIENT_OPT_PREFIX . '-licenseActivation_';
    const OPTION_NAME_NO_USAGE_PREFIX = RPM_WP_CLIENT_OPT_PREFIX . '-noUsage_';
    const INSTALLATION_TYPE_NONE = \false;
    const INSTALLATION_TYPE_DEVELOPMENT = 'development';
    const INSTALLATION_TYPE_PRODUCTION = 'production';
    const ERROR_CODE_NOT_ACTIVATED = 'rpm_wpc_not_activated';
    /** Host check skipped or hostname unresolved — callers must not contact the license server. */
    const ERROR_CODE_HOST_CHECK_BLOCKED = 'rpm_wpc_host_check_blocked';
    /**
     * In some cases, the new host gets validated and RPM automatically deactivates the
     * license of the users without any changes to the host. For some reason, the detected
     * hostname is an invalid "URL" like `http:`.
     */
    const VALIDATE_NEW_HOSTNAME_SKIP = ['http:', 'https:'];
    /**
     * Skip the license deactivation for some exceptions. For example, AWS Lightsail does
     * not automatically redirect the `ec2-192-18[...]` domain to the WordPress domain URL.
     *
     * @see https://regex101.com/r/85EbWA/1
     */
    const VALIDATE_NEW_HOSTNAME_SKIP_BY_REGEXP = '/^(?:\\w+-\\d+-\\d+-\\d+-\\d+\\.[^\\.]+\\.(?:[\\w-]+[-.])?amazonaws\\.com|.*temp\\.domains|\\w+-\\w+\\.[^\\.]+\\.azurewebsites\\.net|[\\w-]+\\.[\\w-]+\\.elb\\.amazonaws\\.com|.*\\.hostingersite\\.com)$/m';
    private $initialized = \false;
    /**
     * Plugin slug.
     *
     * @var string
     */
    private $slug;
    /**
     * Blog id for this license.
     *
     * @var int
     */
    private $blogId;
    /**
     * Hostname at time of creation of this instance.
     *
     * @var string
     */
    private $currentHostname;
    /**
     * Plugin update handler.
     *
     * @var PluginUpdate
     */
    private $pluginUpdate;
    /**
     * License activation handler.
     *
     * @var LicenseActivation
     */
    private $activation;
    /**
     * License telemetry data handler.
     *
     * @var TelemetryData
     */
    private $telemetryData;
    /**
     * Remote status of the activation.
     *
     * @var WP_Error|array
     */
    private $remoteStatus;
    /**
     * Request-local stash of license key + client UUID captured before a clone sever.
     * Not persisted to options.
     *
     * @var array{code: string, uuid: string}|null
     */
    private $severedLicenseIdentityStash = null;
    /**
     * Belt-and-braces reentrancy guard while clearing local identity during sever.
     *
     * @var boolean
     */
    private $severingClonedLicenseIdentity = \false;
    /**
     * One-shot per request: reclaim + programmatic after a successful sever.
     *
     * @var boolean
     */
    private $postSeverRestoreDone = \false;
    /**
     * C'tor.
     *
     * @param PluginUpdate $pluginUpdate
     * @param string $currentHostname
     * @param int $blogId
     * @codeCoverageIgnore
     */
    public function __construct($pluginUpdate, $currentHostname, $blogId)
    {
        $this->pluginUpdate = $pluginUpdate;
        $this->slug = $pluginUpdate->getInitiator()->getPluginSlug();
        $this->currentHostname = $currentHostname;
        $this->blogId = $blogId;
        $this->activation = new LicenseActivation($this);
        $this->telemetryData = new TelemetryData($this);
        $newVersionHook = 'DevOwl/Utils/NewVersionInstallation/' . $this->slug;
        \add_action($newVersionHook, [$this, 'newVersionInstalled']);
        if (\did_action($newVersionHook)) {
            $this->newVersionInstalled();
        }
        if ($this->getInitiator()->isExternalUpdateEnabled() && \is_admin()) {
            \add_action('shutdown', [$this, 'validateNewHostName']);
        }
    }
    /**
     * Initalizes the license once.
     */
    public function initialize()
    {
        if ($this->initialized) {
            return;
        }
        $this->getTelemetryData()->probablyTransmit();
        $this->probablySyncWithRemote();
        $this->probablyMigrate();
        $this->initialized = \true;
    }
    /**
     * A new version of the plugin got installed.
     */
    public function newVersionInstalled()
    {
        // Generate random seconds between 15 minutes and 3 hours
        $delayApiCalls = \mt_rand(15, 3 * 60) * 60;
        $this->getActivation()->executeDeferredAction('licenseActivation', $delayApiCalls);
    }
    /**
     * Switch to this blog.
     *
     * @see https://developer.wordpress.org/reference/functions/switch_to_blog/
     */
    public function switch()
    {
        if (\is_multisite()) {
            \switch_to_blog($this->getBlogId());
        }
    }
    /**
     * Restore to previous blog.
     *
     * @see https://developer.wordpress.org/reference/functions/restore_current_blog/
     */
    public function restore()
    {
        if (\is_multisite()) {
            \restore_current_blog();
        }
    }
    /**
     * If given, read the old license key from the previous updater and give it back as hint.
     */
    public function probablyMigrate()
    {
        $activation = $this->getActivation();
        if ($activation->getCode() !== \false) {
            // We already have a license key, do nothing
            return;
        }
        $this->switch();
        $oldValue = $this->getInitiator()->getMigrationOption();
        $this->restore();
        if ($oldValue !== null) {
            $activation->deactivate(\false, 'warning', \sprintf(
                // translators:
                \__('The plugin has a new update server. Therefore, you need to reactivate your license (%s) to continue receiving updates.', 'devowl-wp-real-product-manager-wp-client'),
                $oldValue
            ) . (\is_multisite() ? ' ' . \__('You are using a WordPress multisite. According to the plugin\'s licence agreement, you need one license per website. If you have only used one licence for all websites in your WordPress multisite, this was only possible because it was not technically prevented. We ask for your understanding if this causes you any inconvenience!', 'devowl-wp-real-product-manager-wp-client') : ''));
        }
    }
    /**
     * Sync our plugin version, PHP version and WordPress version with our remote system.
     */
    public function syncWithRemote()
    {
        $severResult = $this->probablySeverClonedLicenseIdentity();
        if (\is_wp_error($severResult)) {
            return $severResult;
        }
        $activation = $this->getActivation();
        $code = $activation->getCode();
        if (empty($code)) {
            return new WP_Error(License::ERROR_CODE_NOT_ACTIVATED, \__('You have not yet activated a license for this plugin on your website.', 'devowl-wp-real-product-manager-wp-client'), ['blog' => $this->getBlogId(), 'slug' => $this->getSlug()]);
        }
        $this->switch();
        $response = $this->getClient()->patch($code, $this->getUuid(), $activation->isTelemetryDataSharingOptIn());
        $this->restore();
        $this->validateRemoteResponse($response);
        return $response;
    }
    /**
     * The same as `syncWithRemote`, but surely synced only once a day.
     */
    public function probablySyncWithRemote()
    {
        $this->getActivation()->executeDeferredAction('licenseActivation', [$this, 'syncWithRemote']);
    }
    /**
     * Fetch remote status from the Real Product Manager server. Automatically
     * validates with `#validateRemoteResponse`, too.
     *
     * @param boolean $force
     */
    public function fetchRemoteStatus($force = \false)
    {
        $severResult = $this->probablySeverClonedLicenseIdentity();
        if (\is_wp_error($severResult)) {
            return $severResult;
        }
        // Not yet activated, it's an error when asking for remote result
        $code = $this->getActivation()->getCode();
        if (empty($code)) {
            return new WP_Error(self::ERROR_CODE_NOT_ACTIVATED, \__('You have not yet activated a license for this plugin on your website.', 'devowl-wp-real-product-manager-wp-client'), ['blog' => $this->getBlogId(), 'slug' => $this->getSlug()]);
        }
        if ($this->remoteStatus === null || $force) {
            $this->remoteStatus = $this->getClient()->get($code, $this->getUuid());
            $this->validateRemoteResponse($this->remoteStatus);
        }
        return $this->remoteStatus;
    }
    /**
     * If this instance runs on a different host than the one stored with the license
     * (typical after a DB clone to staging), drop local license identity without contacting
     * the license server - otherwise remote DELETE/PATCH/GET would act on production's client UUID.
     *
     * @return bool|WP_Error `true` when local identity was severed, `false` when unchanged
     *                       (or no license identity), `WP_Error` when the host check cannot run
     *                       safely (do not call remote while identity is still present)
     */
    public function probablySeverClonedLicenseIdentity()
    {
        // clearLocal path must not re-enter host checks mid-sever
        if ($this->severingClonedLicenseIdentity) {
            return \true;
        }
        $this->switch();
        $currentHostname = Utils::getCurrentHostname();
        $persistedHostname = $this->getKnownHostname();
        $code = $this->getActivation()->getCode();
        $uuid = $this->getUuid();
        $hasLicenseIdentity = !empty($code) || !empty($uuid);
        $dynamic = \defined('RPM_WP_CLIENT_SKIP_DYNAMIC_HOST_CHECK') && \constant('RPM_WP_CLIENT_SKIP_DYNAMIC_HOST_CHECK');
        // Host check cannot run — with license identity, remote must not use a possibly cloned UUID
        $hostCheckBlocked = empty($currentHostname) || Utils::isRedirected() || $dynamic || \filter_var(\preg_replace('/:[0-9]+/', '', $currentHostname), \FILTER_VALIDATE_IP) !== \false || \parse_url($currentHostname) === \false || \in_array($currentHostname, self::VALIDATE_NEW_HOSTNAME_SKIP, \true) || \preg_match(self::VALIDATE_NEW_HOSTNAME_SKIP_BY_REGEXP, $currentHostname);
        if ($hostCheckBlocked) {
            $this->restore();
            if (!$hasLicenseIdentity) {
                return \false;
            }
            return new WP_Error(self::ERROR_CODE_HOST_CHECK_BLOCKED, \__('The license server cannot be contacted because the website hostname could not be verified safely.', 'devowl-wp-real-product-manager-wp-client'), ['blog' => $this->getBlogId(), 'slug' => $this->getSlug()]);
        }
        if (!$hasLicenseIdentity) {
            $this->restore();
            return \false;
        }
        $severed = \false;
        // Backwards-compatibility, save option of current host
        if (empty($persistedHostname)) {
            if (!empty($code)) {
                \update_option(self::OPTION_NAME_HOST_NAME . $this->getSlug(), \base64_encode($currentHostname));
            }
        } elseif ($currentHostname !== $persistedHostname) {
            // Capture proof before local clear so reclaim can run in this request
            $this->severedLicenseIdentityStash = ['code' => $code, 'uuid' => $uuid];
            $this->severingClonedLicenseIdentity = \true;
            try {
                if (!empty($code)) {
                    $this->getActivation()->clearLocalLicenseIdentity('warning', \__('The license has been automatically deactivated because your website is running on a new domain. Please activate the license again!', 'devowl-wp-real-product-manager-wp-client') . \sprintf(' "%s" -> "%s"', $persistedHostname, $currentHostname) . ($this->getInitiator()->isExternalUpdateEnabled() ? \sprintf(' %s: %s', \__('License key', 'devowl-wp-real-product-manager-wp-client'), $code) : ''), \true);
                } else {
                    \update_option(self::OPTION_NAME_HOST_NAME . $this->getSlug(), '');
                    \update_option(self::OPTION_NAME_UUID_PREFIX . $this->getSlug(), '');
                }
                $severed = \true;
            } finally {
                $this->severingClonedLicenseIdentity = \false;
            }
        }
        $this->restore();
        if ($severed) {
            $this->afterSeverBestEffortRestore();
        }
        return $severed;
    }
    /**
     * Check if the plugin got migrated to another host and deactivate the license automatically.
     * Sever runs reclaim + programmatic via `afterSeverBestEffortRestore` when needed.
     */
    public function validateNewHostName()
    {
        $this->probablySeverClonedLicenseIdentity();
    }
    /**
     * After a successful clone sever in this request: reclaim once, then programmatic activate.
     * Idempotent for the request (`$postSeverRestoreDone`).
     */
    public function afterSeverBestEffortRestore()
    {
        if ($this->postSeverRestoreDone) {
            return;
        }
        $this->postSeverRestoreDone = \true;
        $this->probablyReclaimLicenseActivation();
        $this->activateProgrammatically(\true);
    }
    /**
     * Best-effort reclaim of a prior hostname activation using the sever stash.
     * Any failure is ignored — the caller continues with programmatic / manual flows.
     *
     * @return boolean `true` when local options were restored from reclaim
     */
    public function probablyReclaimLicenseActivation()
    {
        $stash = $this->severedLicenseIdentityStash;
        $this->severedLicenseIdentityStash = null;
        if ($stash === null || empty($stash['code']) || empty($stash['uuid'])) {
            return \false;
        }
        $this->switch();
        $hostname = Utils::getCurrentHostname();
        if (empty($hostname)) {
            $this->restore();
            return \false;
        }
        $response = $this->getClient()->postReclaim($stash['code'], $stash['uuid'], $hostname);
        if (\is_wp_error($response) || !isset($response['licenseActivation'])) {
            $this->restore();
            return \false;
        }
        $this->getActivation()->persistLocalLicenseActivationFromRemote($response['licenseActivation'], $response['featureFlags'] ?? []);
        // After persist (which clears hints): surface a one-time info for the license UI
        $restoredAt = \date_i18n(\get_option('date_format') . ' ' . \get_option('time_format'));
        \update_option(self::OPTION_NAME_HINT_PREFIX . $this->getSlug(), ['validateStatus' => 'info', 'hasFeedback' => \false, 'help' => \sprintf(
            // translators: %s: localized date and time when the license was restored
            \__('Your license was restored automatically on %s. This website is running on a different domain than before (for example after moving the site or creating a staging copy), so an existing activation for this domain was reused and you do not need to enter a license key again.', 'devowl-wp-real-product-manager-wp-client'),
            $restoredAt
        )]);
        $this->getTelemetryData()->probablyTransmit();
        $this->getPluginUpdate()->getLicensedBlogIds(\true);
        $this->restore();
        return \true;
    }
    /**
     * Validate a remote response against their body and probably an error code.
     * It automatically revokes the license if expired/revoked remotely.
     *
     * @param WP_Error|array $response
     */
    public function validateRemoteResponse($response)
    {
        $isError = \is_wp_error($response);
        if ($isError && $response->get_error_code() === ClientUtils::ERROR_CODE_REMOTE) {
            $errorCodes = $response->get_error_codes();
            $errors = $response->get_error_messages();
            foreach ($errorCodes as $index => $errorCode) {
                switch ($errorCode) {
                    case 'ClientNotFound':
                    case 'LicenseActivationNotFound':
                    case 'LicenseHasBeenExpired':
                    case 'LicenseHasBeenRevoked':
                    case 'LicenseNotFound':
                        $this->getActivation()->deactivate(\false, 'warning', \sprintf('%s (%s)', $errors[$index], $this->getActivation()->getCode()));
                        return \false;
                    default:
                        break;
                }
            }
        }
        if (!$isError && isset($response['licenseActivation'])) {
            $licenseActivation = $response['licenseActivation'];
            if (\array_key_exists('featureFlags', $response) && \is_array($response['featureFlags'])) {
                $licenseActivation['featureFlags'] = $response['featureFlags'];
            }
            $this->receivedRemoteLicenseActivation($licenseActivation);
        }
        return \true;
    }
    /**
     * Check if there is a programmatically configured license key and activate it if not already.
     * If there is already an error, it will return that error (expect you pass `$force = true`).
     *
     * @param boolean $force
     */
    public function activateProgrammatically($force = \false)
    {
        $prog = $this->getProgrammaticActivation();
        $activation = $this->getActivation();
        if ($prog === \false) {
            return new WP_Error('rpm_wpc_programmatic_activation_not_found', \__('No programmatic activation found for this plugin.', 'devowl-wp-real-product-manager-wp-client'));
        }
        // If already activated, check if something changed in our filter and reforce
        $code = $activation->getCode();
        $isLicensed = !empty($code);
        if ($isLicensed) {
            $installationType = $activation->getInstallationType();
            if ($code !== $prog['code'] || $installationType !== $prog['type']) {
                $force = \true;
            } else {
                return $activation->getReceived();
            }
        }
        if (!$force) {
            $hint = $activation->getHint();
            if (\is_array($hint) && ($hint['validateStatus'] ?? '') !== 'info') {
                return new WP_Error('rpm_wpc_programmatic_activation_already_error', $hint['help']);
            }
        }
        // Deactivate old license (sever may reclaim first; early-return leaves restored identity)
        if ($isLicensed) {
            $activation->deactivate(\true);
        }
        // After clone sever + reclaim, local key may already match programmatic
        $codeAfter = $activation->getCode();
        if (!empty($codeAfter)) {
            if ($codeAfter === $prog['code'] && $activation->getInstallationType() === $prog['type']) {
                return $activation->getReceived();
            }
            // Same host, different key than filter — intentional remote replace
            $activation->deactivate(\true);
        }
        $result = $activation->activate($prog['code'], $prog['type'], $prog['telemetry'], \false, '', '');
        // Save as hint so our user can see the error message within the license UI
        if (\is_wp_error($result)) {
            \update_option(self::OPTION_NAME_HINT_PREFIX . $this->getSlug(), ['validateStatus' => 'error', 'hasFeedback' => \true, 'help' => \trim(\join(' ', $result->get_error_messages()))]);
        }
        return $result;
    }
    /**
     * We received the remote license activation data. Let's save this to our database
     * so other plugins can act on them.
     *
     * Use cases:
     *
     * - Enable/Disable functionality depending on client properties (Feature flags)
     *
     * @param array $licenseActivation
     */
    public function receivedRemoteLicenseActivation($licenseActivation)
    {
        $this->switch();
        $result = \update_option(License::OPTION_NAME_LICENSE_ACTIVATION_PREFIX . $this->getSlug(), $licenseActivation);
        $this->restore();
        return $result;
    }
    /**
     * Get initiator.
     */
    public function getInitiator()
    {
        return Core::getInstance()->getInitiator($this->getSlug());
    }
    /**
     * Get blog name for this license.
     */
    public function getBlogName()
    {
        $this->switch();
        $result = \sprintf('%s (%s)', \get_bloginfo('name'), Utils::getCurrentHostname());
        $this->restore();
        return $result;
    }
    /**
     * Get known UUID. Can be empty if none given. The UUID will be set with the first
     * license activation.
     *
     * @return string
     */
    public function getUuid()
    {
        $this->switch();
        $result = \get_option(self::OPTION_NAME_UUID_PREFIX . $this->getSlug(), '');
        $this->restore();
        return $result;
    }
    /**
     * Get known hostname. Can be empty if none given. The hostname will be set with the first
     * license activation. The value itself is base64-encoded in database to avoid search & replace
     * mechanism to replace the persisted URL.
     *
     * @return string
     */
    public function getKnownHostname()
    {
        $this->switch();
        $result = \get_option(self::OPTION_NAME_HOST_NAME . $this->getSlug(), '');
        $this->restore();
        return empty($result) ? $result : \base64_decode($result);
    }
    /**
     * Get plugin update handler.
     *
     * @codeCoverageIgnore
     */
    public function getPluginUpdate()
    {
        return $this->pluginUpdate;
    }
    /**
     * Get license activation handler.
     *
     * @codeCoverageIgnore
     */
    public function getActivation()
    {
        return $this->activation;
    }
    /**
     * Get license telemetry data handler.
     *
     * @codeCoverageIgnore
     */
    public function getTelemetryData()
    {
        return $this->telemetryData;
    }
    /**
     * Get plugin slug.
     *
     * @codeCoverageIgnore
     */
    public function getSlug()
    {
        return $this->slug;
    }
    /**
     * Get license client.
     */
    public function getClient()
    {
        return $this->getInitiator()->getPluginUpdater()->getLicenseActivationClient();
    }
    /**
     * Get the license as array, useful for frontend needs or REST API.
     */
    public function getAsArray()
    {
        $remote = $this->fetchRemoteStatus();
        $this->switch();
        $host = Utils::getCurrentHostName();
        $this->restore();
        return ['uuid' => $this->getUuid(), 'blog' => $this->getBlogId(), 'host' => $host, 'programmatically' => $this->getProgrammaticActivation(), 'blogName' => $this->getBlogName(), 'installationType' => $this->getActivation()->getInstallationType(), 'telemetryDataSharingOptIn' => $this->getActivation()->isTelemetryDataSharingOptIn(), 'code' => $this->getActivation()->getCode(), 'hint' => $this->getActivation()->getHint(), 'remote' => \is_wp_error($remote) ? null : $remote, 'noUsage' => $this->isNoUsage()];
    }
    /**
     * See filter `DevOwl/RealProductManager/License/Programmatic/$slug`.
     */
    public function getProgrammaticActivation()
    {
        /**
         * Activate a license programmatically.
         *
         * @hook DevOwl/RealProductManager/License/Programmatic/$slug
         * @example <caption>Example usage for Real Cookie Banner plugin</caption>
         * add_filter(
         *     'DevOwl/RealProductManager/License/Programmatic/real-cookie-banner-pro',
         *     function ($activation, $blogId, $siteUrlHostname) {
         *         if (
         *              // Check if there is already a programmatic activation so we do not overwrite
         *              $activation === false &&
         *              // Check the blog ID within a multisite installation, for non-multisite installation this is always 1
         *              $blogId === 1 &&
         *              // The hostname of your WordPress installation (including subdomain, without path and protocol)
         *              $siteUrlHostname === 'example.your-host.com'
         *         ) {
         *             return [
         *                 // You must pass `true` for the activation to work; you thereby agree to privacy policies of the plugin to be activated
         *                 'optInPrivacyPolicy' => true,
         *                 'key' => 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
         *                 'environment' => 'production', // optional, default: production, can also be `development`
         *                 'telemetry' => true // optional
         *             ];
         *         }
         *         return $activation;
         *     },
         *     10,
         *     3
         * );
         * @param {array|false} $activation The activation for this blog and host, `false` if no filter provides a programmatic activation yet
         * @param {int} $blogId Blog ID within a multisite installation, for non-multisite installation this is always 1
         * @param {string} $siteUrlHostname The hostname of your WordPress installation (including subdomain, without path and protocol)
         * @since 1.11.0
         * @return {array|false}
         */
        $result = \apply_filters('DevOwl/RealProductManager/License/Programmatic/' . $this->getSlug(), \false, $this->getBlogId(), Utils::getCurrentHostname());
        if (\is_array($result) && isset($result['key'])) {
            $key = $result['key'];
            $environment = 'production';
            if (isset($result['environment'])) {
                if (\in_array($environment, ['development', 'production'], \true)) {
                    $environment = $result['environment'];
                } else {
                    // No valid environment
                    return \false;
                }
            }
            $telemetry = \false;
            if (isset($result['telemetry'])) {
                if (\is_bool($result['telemetry'])) {
                    $telemetry = $result['telemetry'];
                } else {
                    // No valid telemetry
                    return \false;
                }
            }
            $optInPrivacyPolicy = $result['optInPrivacyPolicy'] ?? \false;
            if (!$optInPrivacyPolicy) {
                return \false;
            }
            return ['code' => $key, 'type' => $environment, 'telemetry' => $telemetry];
        }
        return \false;
    }
    /**
     * Check if this license needs to have a license key (no usage) and if yes, check if one is given.
     *
     * If you want to check strictly if a license is active do something like `!empty($license->getActivation()->getCode())`.
     */
    public function isFulfilled()
    {
        return $this->isNoUsage() ? \true : !empty($this->getActivation()->getCode());
    }
    /**
     * Check if this license should not be used. It is mostly useful within Multisite when a non-free plugin
     * should be only used on one sub site.
     *
     * @return boolean
     */
    public function isNoUsage()
    {
        // "No usage" is only allowed when more than one unique license is available
        if (\is_multisite() && !$this->getInitiator()->isMultisiteLicensed()) {
            return \false;
        }
        $this->switch();
        $result = \get_option(self::OPTION_NAME_NO_USAGE_PREFIX . $this->getSlug());
        $this->restore();
        return \boolval($result);
    }
    /**
     * Make it work with `array_unique`.
     *
     * @see https://stackoverflow.com/a/2426579/5506547
     */
    public function __toString()
    {
        return \json_encode([$this->getSlug(), $this->getBlogId()]);
    }
    /**
     * Get blog id.
     *
     * @codeCoverageIgnore
     */
    public function getBlogId()
    {
        return $this->blogId;
    }
    /**
     * Getter. See also `getKnownHostname`.
     */
    public function getCurrentHostname()
    {
        return $this->currentHostname;
    }
}
