<?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\Plugins\CoreUpdater;

use Piwik\Config;
use Piwik\Mail;
use Piwik\Option;
use Piwik\Piwik;
use Piwik\Plugins\UsersManager\API as UsersManagerApi;
use Piwik\SettingsPiwik;
use Piwik\UpdateCheck;
use Piwik\Url;
use Piwik\Version;
use Piwik\View;
/**
 * Class to check and notify users via email if there is a core update available.
 */
class UpdateCommunication
{
    /**
     * Checks whether update communication in general is enabled or not.
     *
     * @return bool
     */
    public function isEnabled()
    {
        $isEnabled = (bool) Config::getInstance()->General['enable_update_communication'];
        if ($isEnabled === \true && SettingsPiwik::isInternetEnabled() === \true) {
            return \true;
        }
        return \false;
    }
    /**
     * Sends a notification email to all super users if there is a core update available but only if we haven't notfied
     * them about a specific new version yet.
     */
    public function sendNotificationIfUpdateAvailable() : void
    {
        if (!$this->isNewVersionAvailable()) {
            return;
        }
        if ($this->hasNotificationAlreadyReceived()) {
            return;
        }
        $this->setHasLatestUpdateNotificationReceived();
        $this->sendNotifications();
    }
    protected function sendNotifications()
    {
        $latestVersion = $this->getLatestVersion();
        $host = SettingsPiwik::getPiwikUrl();
        $subject = Piwik::translate('CoreUpdater_NotificationSubjectAvailableCoreUpdate', $latestVersion);
        $view = new View('@CoreUpdater/_updateCommunicationEmail.twig');
        $view->latestVersion = $latestVersion;
        $view->host = $host;
        $version = new Version();
        $view->isStableVersion = $version->isStableVersion($latestVersion);
        $view->linkToChangeLog = $this->getLinkToChangeLog($latestVersion);
        $this->sendEmailNotification($subject, $view);
    }
    private function getLinkToChangeLog($version)
    {
        $version = str_replace('.', '-', $version);
        $link = Url::addCampaignParametersToMatomoLink(sprintf('https://matomo.org/changelog/matomo-%s/', $version));
        return $link;
    }
    /**
     * Send an email notification to all super users.
     *
     * @param $subject
     * @param $message
     */
    protected function sendEmailNotification($subject, $message)
    {
        $superUsers = UsersManagerApi::getInstance()->getUsersHavingSuperUserAccess();
        foreach ($superUsers as $superUser) {
            $mail = new Mail();
            $mail->setDefaultFromPiwik();
            $mail->addTo($superUser['email']);
            $mail->setSubject($subject);
            $mail->setWrappedHtmlBody($message);
            $mail->send();
        }
    }
    protected function isNewVersionAvailable()
    {
        UpdateCheck::check();
        $hasUpdate = UpdateCheck::isNewestVersionAvailable();
        if (!$hasUpdate) {
            return \false;
        }
        $latestVersion = self::getLatestVersion();
        $version = new Version();
        if (!$version->isVersionNumber($latestVersion)) {
            return \false;
        }
        return $hasUpdate;
    }
    protected function hasNotificationAlreadyReceived()
    {
        $latestVersion = $this->getLatestVersion();
        $lastVersionSent = $this->getLatestVersionSent();
        if (!empty($lastVersionSent) && ($latestVersion == $lastVersionSent || version_compare($latestVersion, $lastVersionSent) == -1)) {
            return \true;
        }
        return \false;
    }
    private function getLatestVersion()
    {
        $version = UpdateCheck::getLatestVersion();
        if (!empty($version)) {
            $version = trim($version);
        }
        return $version;
    }
    private function getLatestVersionSent()
    {
        return Option::get($this->getNotificationSentOptionName());
    }
    private function setHasLatestUpdateNotificationReceived()
    {
        $latestVersion = $this->getLatestVersion();
        Option::set($this->getNotificationSentOptionName(), $latestVersion);
    }
    private function getNotificationSentOptionName()
    {
        return 'last_update_communication_sent_core';
    }
}
