# acymailing/trunk/front/FrontControllers/FronturlController.php

AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress, version trunk. 139 lines.

- Page: https://pluginprobe.com/plugins/acymailing/trunk/code/front/FrontControllers/FronturlController.php
- Raw: https://pluginprobe.com/plugins/acymailing/trunk/raw/front/FrontControllers/FronturlController.php
- Modified: 2026-09-03T09:36:36+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/acymailing/trunk/code/front/FrontControllers/FronturlController.php#L10-L20`.

```php
<?php

namespace AcyMailing\FrontControllers;

use AcyMailing\Classes\MailClass;
use AcyMailing\Classes\MailStatClass;
use AcyMailing\Classes\UrlClass;
use AcyMailing\Classes\UrlClickClass;
use AcyMailing\Classes\UserClass;
use AcyMailing\Classes\UserStatClass;
use AcyMailing\Core\AcymController;

class FronturlController extends AcymController
{
    public function __construct()
    {
        parent::__construct();

        $this->publicFrontTasks = [
            'click',
        ];
    }

    public function click(): void
    {
        $urlId = acym_getVar('int', 'urlid');
        $mailId = acym_getVar('int', 'mailid');
        $userId = acym_getVar('int', 'userid');

        $urlClass = new UrlClass();
        $urlObject = $urlClass->getOneUrlById($urlId);

        if (empty($urlObject->id)) {
            acym_raiseError(404, acym_translation('ACYM_PAGE_NOT_FOUND'));
        }

        $urlObject->url = preg_replace(
            [
                '#&idU=[0-9]+#i',
                '#idU=[0-9]+&#i',
                '#\?idU=[0-9]+#i',
            ],
            '',
            $urlObject->url
        );

        $mailClass = new MailClass();
        $mail = $mailClass->getOneById($mailId);

        $userStatClass = new UserStatClass();
        $userStat = $userStatClass->getOneByMailAndUserId($mailId, $userId);

        // The mail has been deleted, or we didn't send this email to this user, or it's a bot
        $delay = $this->config->get('tracking_delay', 0);
        if (empty($mail) || empty($userStat) || acym_isRobot() || (!empty($delay) && acym_getTimeFromUTCDate($userStat->send_date) > time() - $delay)) {
            acym_redirect($this->resolveSubscriberTags($urlObject->url, $userId), '', 'message', false);
        }

        $anonymousStats = !empty($this->config->get('anonymous_stats', 0));

        $urlClick = new \stdClass();
        $urlClick->mail_id = $mailId;
        $urlClick->url_id = $urlObject->id;
        $urlClick->click = 1;
        $urlClick->user_id = $anonymousStats ? 0 : $userId;
        $urlClick->date_click = acym_date('now', 'Y-m-d H:i:s', false);

        $mailStatClass = new MailStatClass();
        $urlClickClass = new UrlClickClass();
        $urlClickClass->save($urlClick);

        UserStatClass::triggerActivity('user_click', $userId, $mailId);

        if (!$anonymousStats) {
            if (empty($userStat->open)) {
                $userStatToInsert = new \stdClass();
                $userStatToInsert->user_id = $userId;
                $userStatToInsert->mail_id = $mailId;
                $userStatToInsert->open = 1;
                $userStatToInsert->open_date = acym_date('now', 'Y-m-d H:i:s', false);
                $userStatClass->save($userStatToInsert);

                $mailStat = new \stdClass();
                $mailStat->mail_id = $mailId;
                $mailStat->open_unique = 1;
                $mailStat->open_total = 1;
                $mailStatClass->save($mailStat);

                UserStatClass::triggerActivity('user_open', $userId, $mailId);
            }

            $clickStats = $urlClickClass->getOneByMailIdAndUserId($mailId, $userId);
            $mailStatClass->incrementClicks($mailId, $clickStats->click == 1);
        } else {
            $mailStatClass->incrementClicks($mailId, true);

            // Anonymous mode tracks totals only and keeps no per-recipient open state, so this is not deduplicated.
            $mailStat = new \stdClass();
            $mailStat->mail_id = $mailId;
            $mailStat->open_unique = 1;
            $mailStat->open_total = 1;
            $mailStatClass->save($mailStat);
            $mailStatClass->incrementDetail($mailId, 'open_time', acym_date('now', 'Y-m-d H', false).':00:00');
        }

        $userClass = new UserClass();
        $subscriber = $userClass->getOneById($userId);
        if (!empty($subscriber)) {
            $subscriber->last_open_date = acym_date('now', 'Y-m-d H:i:s', false);
            $subscriber->last_click_date = acym_date('now', 'Y-m-d H:i:s', false);
            $userClass->triggers = false;
            $userClass->sendConf = false;
            $userClass->save($subscriber);
        }

        acym_redirect($this->resolveSubscriberTags($urlObject->url, $userId), '', 'message', false);
    }

    private function resolveSubscriberTags(string $url, int $userId): string
    {
        if (!preg_match('#\{|%7B#i', $url)) {
            return $url;
        }

        $userClass = new UserClass();
        $subscriber = $userClass->identify(true, 'userid', 'userkey');

        if (empty($subscriber) || (int)$subscriber->id !== $userId) {
            return $url;
        }

        $tempEmail = new \stdClass();
        $tempEmail->body = $url;
        acym_trigger('replaceUserInformation', [&$tempEmail, &$subscriber, true]);

        return $tempEmail->body;
    }
}

```
