jon48/webtrees-lib

View on GitHub
app/Module/WelcomeBlock/Services/MatomoStatsService.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

/**
 * webtrees-lib: MyArtJaub library for webtrees
 *
 * @package MyArtJaub\Webtrees
 * @subpackage WelcomeBlock
 * @author Jonathan Jaubart <dev@jaubart.com>
 * @copyright Copyright (c) 2020-2022, Jonathan Jaubart
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
 */

declare(strict_types=1);

namespace MyArtJaub\Webtrees\Module\WelcomeBlock\Services;

use Carbon\Carbon;
use Fig\Http\Message\StatusCodeInterface;
use Fisharebest\Webtrees\Registry;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\RequestOptions;
use GuzzleHttp\Exception\GuzzleException;
use MyArtJaub\Webtrees\Module\WelcomeBlock\WelcomeBlockModule;

/**
 * Service for retrieving Matomo statistics
 *
 */
class MatomoStatsService
{
    protected ?HandlerStack $handler = null;

    /**
     * Set or get the http handler for the service
     *
     * @param HandlerStack $handler
     * @return HandlerStack
     */
    public function httpHandler(HandlerStack $handler = null): HandlerStack
    {
        if ($this->handler === null) {
            $this->handler = HandlerStack::create();
        }
        if ($handler !== null) {
            $this->handler = $handler;
        }
        return $this->handler;
    }

    /**
     * Returns the number of visits for the current year (up to the day before).
     * That statistic is cached for the day, to avoid unecessary calls to Matomo API.
     *
     * @param WelcomeBlockModule $module
     * @param int $block_id
     * @return int|NULL
     */
    public function visitsThisYear(WelcomeBlockModule $module, int $block_id): ?int
    {
        return Registry::cache()->file()->remember(
            $module->name() . '-matomovisits-yearly-' . $block_id,
            function () use ($module, $block_id): ?int {
                $visits_year = $this->visits($module, $block_id, 'year');
                if ($visits_year === null) {
                    return null;
                }
                $visits_today = (int) $this->visits($module, $block_id, 'day');

                return $visits_year - $visits_today;
            },
            Carbon::now()->addDay()->startOfDay()->diffInSeconds(Carbon::now()) // Valid until midnight
        );
    }

    /**
     * Returns the number of visits for the current day.
     *
     * @param WelcomeBlockModule $module
     * @param int $block_id
     * @return int|NULL
     */
    public function visitsToday(WelcomeBlockModule $module, int $block_id): ?int
    {
        return Registry::cache()->array()->remember(
            $module->name() . '-matomovisits-daily-' . $block_id,
            function () use ($module, $block_id): ?int {
                return $this->visits($module, $block_id, 'day');
            }
        );
    }

    /**
     * Invoke the Matomo API to retrieve the number of visits over a period.
     *
     * @param WelcomeBlockModule $module
     * @param int $block_id
     * @param string $period
     * @return int|NULL
     */
    protected function visits(WelcomeBlockModule $module, int $block_id, string $period): ?int
    {
        $settings = $module->matomoSettings($block_id);

        if (
            $settings['matomo_enabled'] === true
            && mb_strlen($settings['matomo_url']) > 0
            && mb_strlen($settings['matomo_token']) > 0
            && $settings['matomo_siteid'] > 0
        ) {
            try {
                $http_client = new Client([
                    RequestOptions::TIMEOUT => 30,
                    'handler'   => $this->handler
                ]);

                $response = $http_client->get($settings['matomo_url'], [
                    'query' =>  [
                        'module'    =>  'API',
                        'method'    =>  'VisitsSummary.getVisits',
                        'idSite'    =>  $settings['matomo_siteid'],
                        'period'    =>  $period,
                        'date'      =>  'today',
                        'token_auth' =>  $settings['matomo_token'],
                        'format'    =>  'json'
                    ]
                ]);

                if ($response->getStatusCode() === StatusCodeInterface::STATUS_OK) {
                    $result = json_decode((string) $response->getBody(), true)['value'] ?? null;
                    if ($result !== null) {
                        return (int)$result;
                    }
                }
            } catch (GuzzleException $ex) {
            }
        }

        return null;
    }
}