
<center><h2><strong>Ubuntu</strong></h2>
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
<?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\ScheduledReports;

use Piwik\Access;
use Piwik\API\Request;
use Piwik\Common;
use Piwik\Db;
use Piwik\DbHelper;
use Piwik\Piwik;
use Piwik\Plugins\ScheduledReports\API as APIScheduledReports;
class SubscriptionModel
{
    private static $rawPrefix = 'report_subscriptions';
    private $table;
    public function __construct()
    {
        $this->table = Common::prefixTable(self::$rawPrefix);
    }
    public function unsubscribe($token)
    {
        $details = $this->getSubscription($token);
        if (empty($details)) {
            return \false;
        }
        $email = $details['email'];
        /*
         * Executed as super user, as we need to fetch a scheduled report, without the current user being authenticated.
         */
        $report = Access::doAsSuperUser(function () use($details) {
            $reports = Request::processRequest('ScheduledReports.getReports', array('idReport' => $details['idreport']));
            return reset($reports);
        });
        if (empty($report)) {
            // if the report isn't found, remove subscription as it isn't active anymore
            $this->removeSubscription($token);
            return \false;
        }
        $reportParameters = $report['parameters'];
        $emailFound = \false;
        if (!empty($reportParameters['additionalEmails'])) {
            $additionalEmails = $reportParameters['additionalEmails'];
            $filteredEmails = [];
            foreach ($additionalEmails as $additionalEmail) {
                if ($additionalEmail == $email) {
                    $emailFound = \true;
                    continue;
                }
                $filteredEmails[] = $additionalEmail;
            }
            if ($emailFound) {
                $report['parameters']['additionalEmails'] = $filteredEmails;
            }
        }
        if ($reportParameters['emailMe']) {
            $login = $report['login'];
            $userModel = new \Piwik\Plugins\UsersManager\Model();
            $userData = $userModel->getUser($login);
            if ($userData['email'] == $email) {
                $emailFound = \true;
                $report['parameters']['emailMe'] = \false;
            }
        }
        if ($emailFound) {
            $reportModel = new \Piwik\Plugins\ScheduledReports\Model();
            $reportModel->updateReport($report['idreport'], array('parameters' => json_encode($report['parameters'])));
            // Reset the cache manually since we didn't call the API method which would do it for us
            APIScheduledReports::$cache = array();
            Piwik::postEvent('Report.unsubscribe', [$report['idreport'], $email]);
            $this->removeSubscription($token);
        }
        return $emailFound;
    }
    public function getReportSubscriptions($idReport, $includeUnsubscribed = \false)
    {
        $query = 'SELECT * FROM ' . $this->table . ' WHERE idreport = ?';
        if (!$includeUnsubscribed) {
            $query .= ' AND ts_unsubscribed IS NULL';
        }
        return $this->getDb()->fetchAll($query, [$idReport]);
    }
    public function getSubscription($token)
    {
        return $this->getDb()->fetchRow('SELECT * FROM ' . $this->table . ' WHERE token = ?', [$token]);
    }
    public function updateReportSubscriptions($idReport, $emails)
    {
        $availableSubscriptions = $this->getReportSubscriptions($idReport);
        $availableEmails = array_column($availableSubscriptions, 'email');
        // remove available subscriptions that aren't present anymore
        foreach ($availableSubscriptions as $availableSubscription) {
            if (!in_array($availableSubscription['email'], $emails) && !empty($availableSubscription['token'])) {
                $this->removeSubscription($availableSubscription['token']);
            }
        }
        $emails = array_unique($emails);
        // add new subscriptions
        foreach ($emails as $email) {
            while ($token = $this->generateToken($email)) {
                if (!$this->tokenExists($token)) {
                    break;
                }
            }
            if (!in_array($email, $availableEmails)) {
                $subscription = ['idreport' => $idReport, 'token' => $token, 'email' => $email];
                // remove possible "unsubscribe" entry
                $this->getDb()->query('DELETE FROM ' . $this->table . ' WHERE idreport = ? AND email = ?', [$idReport, $email]);
                $this->getDb()->insert($this->table, $subscription);
            }
        }
    }
    private function removeSubscription($token)
    {
        $this->getDb()->query('UPDATE ' . $this->table . ' SET token = NULL, ts_unsubscribed = NOW() WHERE token = ?', [$token]);
    }
    private function generateToken($email)
    {
        return substr(Common::hash($email . time() . Common::getRandomString(5)), 0, 100);
    }
    private function tokenExists($token)
    {
        return !!$this->getDb()->fetchOne('SELECT token FROM ' . $this->table . ' WHERE token = ?', [$token]);
    }
    private function getDb()
    {
        return Db::get();
    }
    public static function install()
    {
        $reportTable = "`idreport` INT(11) NOT NULL,\n\t\t\t\t\t    `token` VARCHAR(100) NULL,\n\t\t\t\t\t    `email` VARCHAR(100) NOT NULL,\n\t\t\t\t\t    `ts_subscribed` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n\t\t\t\t\t    `ts_unsubscribed` TIMESTAMP NULL,\n\t\t\t\t\t    PRIMARY KEY (`idreport`, `email`),\n\t\t\t\t\t    UNIQUE INDEX `unique_token` (`token`)";
        DbHelper::createTable(self::$rawPrefix, $reportTable);
    }
}
