HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/app/Http/Controllers/Pub/MailListController.php
<?php

namespace App\Http\Controllers\Pub;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Model\MailList;
use App\Model\IpLocation;
use App\Model\Subscriber;
use App\Library\StringHelper;
use App\Library\SubscriberUrlTagResolver;
use App\Services\SubscriberService;
use App\Services\TagTranslationService;
use RuntimeException;

class MailListController extends Controller
{
    /**
     * Sign up form page.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Response
     */
    public function signUpForm(Request $request)
    {
        $subscriberService = app(SubscriberService::class);
        $customerUid = $request->customer_uid;
        $customer = \App\Model\Customer::findByUid($customerUid);

        if (is_null($customer)) {
            throw new \Exception('Cannot find customer');
        } else {
            $customer->setUserDbConnection();
        }

        $list = \App\Model\MailList::findByUid($request->list_uid);
        $mailListTemplate = $list->getTemplate('sign_up_form');

        $logger = applog("optin-for-customer-{$customerUid}-list-{$list->uid}");

        // Language
        if ($list->customer->language) {
            \App::setLocale($list->customer->language->code);
            \Carbon\Carbon::setLocale($list->customer->language->code);
        }

        // Get old post values
        $values = [];
        if (null !== $request->old()) {
            foreach ($request->old() as $key => $value) {
                if (is_array($value)) {
                    $values[str_replace('[]', '', $key)] = implode(',', $value);
                } else {
                    $values[$key] = $value;
                }
            }
        }

        // Create subscriber
        if ($request->isMethod('post')) {
            // Captcha check — fail-open: any vendor rejection lets the
            // signup through but dispatches an admin notification. See
            // App\Library\Tool::verifyCaptchaOrAlert.
            if (\App\Model\Setting::isListSignupCaptchaEnabled()) {
                \App\Library\Tool::verifyCaptchaOrAlert($request, 'list-signup');
            }

            try {
                $logger->info('Opting in through default opt-in page '.$request->EMAIL);
                [$validator, $subscriber] = $subscriberService->optInFromWeb($list, $request, $logger);
            } catch (\Exception $ex) {
                $logger->info('Failed to opt in: '.$request->EMAIL);
                return view('somethingWentWrong', ['message' => $ex->getMessage()]);
            }

            if ($validator->fails()) {
                return back()->withErrors($validator)->withInput();
            }

            $logger->info('Done opting in: '.$subscriber->email);

            // Timeline record
            if ($request->redirect_url) {
                $logger->info("Redirecting {$subscriber->email} to {$request->redirect_url}");
                return redirect()->away($request->redirect_url);
            } elseif ($list->subscribe_confirmation && !$subscriber->isSubscribed()) {
                // tell subscriber to check email for confirmation
                $logger->info("Redirect {$subscriber->email} to ThankYou page, asking user to check email to confirm (double opt-in)");
                return redirect()->action('Pub\MailListController@signUpThankyouPage', ['list_uid' => $list->uid, 'subscriber_id' => $subscriber->id, 'customer_uid' => $list->customer->uid]);
            } else {
                // All done, confirmed
                $logger->info("All done, redirect {$subscriber->email} to Pub\MailListController@thankYou");
                return redirect()->away($subscriberService->generateSignedConfirmationUrl($subscriber));
            }
        }

        $html = $mailListTemplate->renderContent($values);

        // wrapping html with form tag. html is <html>...<html>. wrap body only
        $dom = new \DOMDocument();
        libxml_use_internal_errors(true);
        $dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
        libxml_clear_errors();

        // DOMDocument::loadHTML auto-creates <html>/<body> for any non-empty flow
        // content. The only inputs that produce a null body are: empty/whitespace,
        // <head>-only, comments-only, or broken-encoding templates — all of which
        // mean the template is unusable, so fail loud instead of rendering broken.
        $body = $dom->getElementsByTagName('body')->item(0);
        if ($body === null) {
            throw new \RuntimeException(sprintf(
                'MailList template produced no body content. list_uid=%s template_id=%s',
                $list->uid,
                $mailListTemplate->id ?? 'null'
            ));
        }
        $form = $dom->createElement('form');
        $form->setAttribute('method', 'post');
        $form->setAttribute('action', action('Pub\MailListController@signUpForm', ['list_uid' => $list->uid, 'customer_uid' => $list->customer->uid]));
        $form->setAttribute('autocomplete', 'off');

        // Move all body content into the form
        while ($body->hasChildNodes()) {
            $form->appendChild($body->removeChild($body->firstChild));
        }

        // Add form to body
        $body->appendChild($form);

        return $dom->saveHTML();

    }

    /**
     * Sign up thank you page.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Response
     */
    public function signUpThankyouPage(Request $request)
    {
        $customerUid = $request->customer_uid;
        $customer = \App\Model\Customer::findByUid($customerUid);

        if (is_null($customer)) {
            throw new \Exception('Cannot find customer');
        } else {
            $customer->setUserDbConnection();
        }

        $list = \App\Model\MailList::findByUid($request->list_uid);
        $mailListTemplate = $list->getTemplate('sign_up_confirmation_page');
        $subscriber = \App\Model\Subscriber::find($request->subscriber_id);

        // Language
        if ($list->customer && $list->customer->language) {
            \App::setLocale($list->customer->language->code);
            \Carbon\Carbon::setLocale($list->customer->language->code);
        }

        // redirect if use outside url
        if ($list->sign_up_confirmation_page_use_outside_url) {
            return redirect($list->sign_up_confirmation_page_outside_url);
        }

        return $mailListTemplate->renderContent(null, $subscriber);
    }

    /**
     * Sign up confirmation thank you page.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse|string
     */
    public function thankYou(Request $request)
    {
        $subscriberService = app(SubscriberService::class);
        $customerUid = $request->customer_uid;
        $customer = \App\Model\Customer::findByUid($customerUid);

        if (is_null($customer)) {
            throw new \Exception('Cannot find customer');
        } else {
            $customer->setUserDbConnection();
        }

        $list = \App\Model\MailList::findByUid($request->list_uid);
        $mailListTemplate = $list->getTemplate('sign_up_thankyou_page');
        $subscriber = \App\Model\Subscriber::find($request->id);

        // Language
        if ($list->customer && $list->customer->language) {
            \App::setLocale($list->customer->language->code);
            \Carbon\Carbon::setLocale($list->customer->language->code);
        }

        if (is_null($subscriber)) {
            return "Subscriber no longer exists";
        }

        if ((int) $list->customer_id !== (int) $customer->id || (int) $subscriber->mail_list_id !== (int) $list->id) {
            abort(404);
        }

        try {
            $subscriberService->confirmOptIn($subscriber);
        } catch (RuntimeException $ex) {
            abort(409, $ex->getMessage());
        }

        // redirect if use outside url
        if ($list->sign_up_thankyou_page_use_outside_url) {
            return redirect($this->transformOutsideUrl($list->sign_up_thankyou_page_outside_url, $subscriber));
        }

        return $mailListTemplate->renderContent(null, $subscriber);
    }

    /**
     * Update profile form.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Response
     */
    public function profileUpdateForm(Request $request)
    {
        $customerUid = $request->customer_uid;
        $customer = \App\Model\Customer::findByUid($customerUid);

        if (is_null($customer)) {
            throw new \Exception("Cannot find customer: '{$customerUid}'");
        } else {
            $customer->setUserDbConnection();
        }

        $list = \App\Model\MailList::findByUid($request->list_uid);
        $subscriber = \App\Model\Subscriber::find($request->id);
        $mailListTemplate = $list->getTemplate('profile_update_form');

        if (is_null($subscriber) || is_null($list)) {
            abort(404);
        }

        // Language
        if ($list->customer && $list->customer->language) {
            \App::setLocale($list->customer->language->code);
            \Carbon\Carbon::setLocale($list->customer->language->code);
        }

        $values = [];

        // Fetch subscriber fields to values
        foreach ($list->fields as $key => $field) {
            $value = $subscriber->getValueByField($field);
            if (is_array($value)) {
                $values[str_replace('[]', '', $key)] = implode(',', $value);
            } else {
                $values[$field->tag] = $value;
            }
        }

        // Get old post values
        if (null !== $request->old()) {
            foreach ($request->old() as $key => $value) {
                if (is_array($value)) {
                    $values[str_replace('[]', '', $key)] = implode(',', $value);
                } else {
                    $values[$key] = $value;
                }
            }
        }

        if ($request->isMethod('post')) {
            $rules = $subscriber->getRules();
            $rules['EMAIL'] .= '|in:'.$subscriber->email;
            // Validation
            $this->validate($request, $rules);

            // Update field
            $subscriber->updateFields($request->all());

            return redirect()->action('Pub\MailListController@profileUpdateSuccessPage', ['list_uid' => $list->uid, 'id' => $subscriber->id, 'customer_uid' => $list->customer->uid]);
        }

        $html = $mailListTemplate->renderContent($values, $subscriber);

        // wrapping html with form tag. html is <html>...<html>. wrap body only
        $dom = new \DOMDocument();
        libxml_use_internal_errors(true);
        $dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
        libxml_clear_errors();

        // DOMDocument::loadHTML auto-creates <html>/<body> for any non-empty flow
        // content. The only inputs that produce a null body are: empty/whitespace,
        // <head>-only, comments-only, or broken-encoding templates — all of which
        // mean the template is unusable, so fail loud instead of rendering broken.
        $body = $dom->getElementsByTagName('body')->item(0);
        if ($body === null) {
            throw new \RuntimeException(sprintf(
                'MailList template produced no body content. list_uid=%s template_id=%s',
                $list->uid,
                $mailListTemplate->id ?? 'null'
            ));
        }
        $form = $dom->createElement('form');
        $form->setAttribute('method', 'post');
        $form->setAttribute('action', action('Pub\MailListController@profileUpdateForm', ['list_uid' => $list->uid, 'id' => $subscriber->id, 'customer_uid' => $list->customer->uid]));
        $form->setAttribute('autocomplete', 'off');

        // Move all body content into the form
        while ($body->hasChildNodes()) {
            $form->appendChild($body->removeChild($body->firstChild));
        }

        // Add form to body
        $body->appendChild($form);

        return $dom->saveHTML();
    }

    /**
     * Update profile success.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse|string
     */
    public function profileUpdateSuccessPage(Request $request)
    {
        $customerUid = $request->customer_uid;
        $customer = \App\Model\Customer::findByUid($customerUid);

        if (is_null($customer)) {
            throw new \Exception('Cannot find customer');
        } else {
            $customer->setUserDbConnection();
        }

        $list = \App\Model\MailList::findByUid($request->list_uid);
        $subscriber = \App\Model\Subscriber::find($request->id);
        $mailListTemplate = $list->getTemplate('profile_update_success_page');

        // Language
        if ($list->customer && $list->customer->language) {
            \App::setLocale($list->customer->language->code);
            \Carbon\Carbon::setLocale($list->customer->language->code);
        }

        // redirect if use outside url
        if ($mailListTemplate->profile_update_success_page_use_outside_url) {
            return redirect($this->transformOutsideUrl($mailListTemplate->profile_update_success_page_outside_url, $subscriber));
        }

        return $mailListTemplate->renderContent(null, $subscriber);
    }

    /**
     * Send update profile request.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse|\Illuminate\View\View|string
     */
    public function profileUpdateEmailSent(Request $request)
    {
        $customerUid = $request->customer_uid;
        $customer = \App\Model\Customer::findByUid($customerUid);

        if (is_null($customer)) {
            throw new \Exception('Cannot find customer');
        } else {
            $customer->setUserDbConnection();
        }

        $list = \App\Model\MailList::findByUid($request->list_uid);
        $subscriber = \App\Model\Subscriber::find($request->id);
        $mailListTemplate = $list->getTemplate('profile_update_email_sent');

        // Language
        if ($list->customer && $list->customer->language) {
            \App::setLocale($list->customer->language->code);
            \Carbon\Carbon::setLocale($list->customer->language->code);
        }

        // SEND EMAIL
        try {
            $list->sendProfileUpdateEmail($subscriber);
        } catch (\Exception $ex) {
            return view('somethingWentWrong', ['message' => $ex->getMessage()]);
        }

        // redirect if use outside url
        if ($mailListTemplate->profile_update_email_sent_use_outside_url) {
            return redirect($this->transformOutsideUrl($mailListTemplate->profile_update_email_sent_outside_url, $subscriber));
        }

        return $mailListTemplate->renderContent(null, $subscriber);
    }

    /**
     * Render a customer-configured outside-redirect URL with subscriber tags
     * substituted ({{ SUBSCRIBER_<FIELD> }}, {{ EMAIL }}, {{ FIRST_NAME }}, …)
     * and append `subscriber_id` so the destination can identify the visitor.
     */
    private function transformOutsideUrl(string $url, Subscriber $subscriber): string
    {
        $url = app(TagTranslationService::class)
            ->translate($url, new SubscriberUrlTagResolver($subscriber));

        $separator = parse_url($url, PHP_URL_QUERY) ? '&' : '?';
        return $url . $separator . 'subscriber_id=' . $subscriber->id;
    }
}