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/be.naniguide.com/app/Http/Controllers/Refactor/FormController.php
<?php

namespace App\Http\Controllers\Refactor;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Model\Form;
use App\Model\FormTemplate;
use Gate;

class FormController extends Controller
{
    public function index(Request $request)
    {
        if (Gate::denies('list', Form::class)) {
            return $this->notAuthorized();
        }

        $customer = $request->user()->customer;
        $totalForms = $customer->local()->forms()->count();
        $published = $customer->local()->forms()->where('status', 'published')->count();
        $draft = $customer->local()->forms()->where('status', 'draft')->count();

        $websites = $customer->local()->websites()->connected()->orderBy('title')->get();

        return view('refactor.pages.forms.index', [
            'customer' => $customer,
            'totalForms' => $totalForms,
            'published' => $published,
            'draft' => $draft,
            'websites' => $websites,
        ]);
    }

    public function listing(Request $request)
    {
        if (Gate::denies('list', Form::class)) {
            return $this->notAuthorized();
        }

        $query = $request->user()->customer->local()->forms()
            ->search($request->keyword)
            ->filter($request->all());

        // Status filter
        if (!empty($request->status)) {
            $query->where('status', $request->status);
        }

        $forms = $query
            ->orderBy($request->sort_order ?? 'created_at', $request->sort_direction ?? 'desc')
            ->paginate($request->per_page ?? 25);

        return view('refactor.pages.forms._list', [
            'forms' => $forms,
        ]);
    }

    public function create(Request $request)
    {
        $form = Form::newDefault($request->user()->customer);

        if (Gate::denies('create', Form::class)) {
            return $this->notAuthorized();
        }

        if ($request->isMethod('post')) {
            $validator = $form->createFromArray($request->all());

            if ($validator->fails()) {
                return response()->json([
                    'errors' => $validator->errors(),
                ], 422);
            }

            return response()->json([
                'message' => trans('refactor/forms.flash.created'),
                'redirect' => route('refactor.forms.builder', $form->uid),
            ]);
        }

        return view('refactor.pages.forms.create', [
            'form' => $form,
        ]);
    }

    public function delete(Request $request)
    {
        $forms = Form::whereIn(
            'uid',
            is_array($request->uids) ? $request->uids : explode(',', $request->uids)
        );

        $total = $forms->count();
        $deleted = 0;
        foreach ($forms->get() as $form) {
            if ($request->user()->customer->can('delete', $form)) {
                $form->delete();
                $deleted++;
            }
        }

        return response()->json([
            'message' => $deleted . ' ' . trans('refactor/forms.flash.deleted'),
        ]);
    }

    public function publish(Request $request)
    {
        $forms = Form::whereIn(
            'uid',
            is_array($request->uids) ? $request->uids : explode(',', $request->uids)
        );

        foreach ($forms->get() as $form) {
            if ($request->user()->customer->can('update', $form)) {
                $form->publish();
            }
        }

        return response()->json(['message' => trans('refactor/forms.flash.published')]);
    }

    public function unpublish(Request $request)
    {
        $forms = Form::whereIn(
            'uid',
            is_array($request->uids) ? $request->uids : explode(',', $request->uids)
        );

        foreach ($forms->get() as $form) {
            if ($request->user()->customer->can('update', $form)) {
                $form->unpublish();
            }
        }

        return response()->json(['message' => trans('refactor/forms.flash.unpublished')]);
    }

    public function builder(Request $request, $uid)
    {
        $form = \App\Model\Form::findByUid($uid);

        if (!$form || \Gate::denies('update', $form)) {
            return $this->notAuthorized();
        }

        $template = $form->template;

        // If the form has no template assigned, redirect to forms index with an
        // error rather than crashing on $template->getThemeMetadata() in the view.
        if (!$template) {
            return redirect()->route('refactor.forms.index')
                ->with('alert-danger', 'This form has no template assigned. Please recreate it.');
        }

        // Form fields for Builder widgets
        $formFields = $form->mailList->getFields->map(function ($field) {
            return [
                'type' => $field->tag == 'EMAIL' ? 'email' : $field->type,
                'label' => $field->label,
                'name' => $field->tag,
                'visible' => $field->visible,
                'required' => $field->required,
                'default' => $field->default_value,
                'options' => $field->fieldOptions->map(function ($option) {
                    return ['value' => $option->value, 'text' => $option->label];
                })->toArray(),
            ];
        })->toArray();

        // List context for builder sidebar info card
        $mailList = $form->mailList;
        $listInfo = [
            'name' => $mailList->name,
            'from_name' => $mailList->from_name,
            'from_email' => $mailList->from_email,
            'subscriber_count' => $mailList->subscribersCount(true) ?? 0,
            'field_count' => count($formFields),
        ];

        // Form templates for layout gallery
        $formTemplates = FormTemplate::get();
        $templates = $formTemplates->map(function ($ft) {
            return $ft->template;
        })->filter();

        // Tags for the builder
        $tags = $form->getBuilderTags();

        return view('refactor.pages.forms.builder', [
            'form' => $form,
            'template' => $template,
            'formFields' => $formFields,
            'listInfo' => $listInfo,
            'templates' => $templates,
            'tags' => $tags,
            'customer' => $form->customer,
        ]);
    }

    public function preview(Request $request, $uid)
    {
        $form = Form::findByUid($uid);

        if (!$form || Gate::denies('read', $form)) {
            return $this->notAuthorized();
        }

        // Wrap the raw saved HTML in a minimal document that links the
        // public popup stylesheet PLUS inlines the critical Terms-widget
        // layout rules directly inside <style>. Without this, the preview
        // iframe served raw body markup with no stylesheet — class-based
        // defensive rules (e.g. `.acm-terms--inline { display: flex }` for
        // legacy saved forms that lack the inline-style version of the
        // template) never applied, and any widget shape relying on class
        // fallbacks rendered as a stacked default-block layout.
        //
        // The inline `<style>` block is the SAME ruleset as
        // `public/core/css/form_popup_content.css` (Terms-widget section).
        // Inlining guarantees the rules apply even if the iframe sandbox /
        // network conditions block the external link request — robust path,
        // no race with link-load timing.
        $cssUrl = url('core/css/form_popup_content.css') . '?v=' . time();
        $body = $form->renderedContent();
        $inlineStyles = <<<'CSS'
/* Universal jQuery validate error placement — every form field inside the
   preview iframe gets the same inline error styling as production (kept in
   sync with public/core/css/form_popup_content.css). The Terms-widget
   `.acm-terms label.error` rules below override this with !important. */
form label.error,
[data-form-container-wrapper] label.error {
    display: block !important;
    margin: 4px 0 0 0;
    font-size: 12px;
    line-height: 1.4;
    color: #dc3545;
}
.acm-terms__text a { color: inherit; text-decoration: underline; }
.acm-terms__agree {
    display: flex; flex-wrap: wrap; align-items: flex-start;
    gap: 8px; cursor: pointer; user-select: none; margin: 0;
}
.acm-terms__agree > .acm-terms__input { flex: 0 0 auto; margin-top: 3px; }
.acm-terms__agree > .acm-terms__agree-label { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; word-break: break-word; line-height: 1.45; }
.acm-terms--inline {
    display: flex !important; flex-wrap: wrap !important; align-items: flex-start !important; gap: 8px !important;
}
.acm-terms--inline > .acm-terms__input { flex: 0 0 auto !important; margin-top: 3px; }
.acm-terms--inline > .acm-terms__text  { flex: 1 1 0 !important; min-width: 0 !important; overflow-wrap: anywhere; word-break: break-word; }
.acm-terms label.error,
.acm-terms__agree label.error {
    order: 99 !important; flex: 0 0 100% !important; width: 100% !important;
    margin: 6px 0 0 0 !important; padding: 0 !important;
    font-size: 12px !important; line-height: 1.4 !important;
    font-weight: 400 !important; color: #dc3545 !important;
    display: block !important;
}
CSS;

        $html = '<!doctype html><html><head><meta charset="utf-8">'
            . '<meta name="viewport" content="width=device-width,initial-scale=1">'
            . '<title>' . e($form->name) . '</title>'
            . '<link rel="stylesheet" href="' . e($cssUrl) . '">'
            . '<style>' . $inlineStyles . '</style>'
            . '</head><body>' . $body . '</body></html>';

        return response($html)
            ->header('Content-Type', 'text/html; charset=UTF-8');
    }

    public function connect(Request $request, $uid)
    {
        $form = Form::findByUid($uid);

        if (!$form || Gate::denies('update', $form)) {
            return $this->notAuthorized();
        }

        return view('refactor.pages.forms.connect', [
            'form' => $form,
        ]);
    }

    public function connectSave(Request $request, $uid)
    {
        $form = Form::findByUid($uid);

        if (!$form || Gate::denies('update', $form)) {
            return $this->notAuthorized();
        }

        $validator = \Validator::make($request->all(), [
            'website_uid' => 'required',
        ]);

        if ($validator->fails()) {
            return response()->view('refactor.pages.forms.connect', [
                'form' => $form,
                'errors' => $validator->errors(),
            ], 400);
        }

        $site = \App\Model\Website::findByUid($request->website_uid);
        $form->connect($site);

        return response()->json([
            'message' => trans('refactor/forms_builder.connected', ['site' => $site->title]),
        ]);
    }

    public function disconnect(Request $request, $uid)
    {
        $form = Form::findByUid($uid);

        if (!$form || Gate::denies('update', $form)) {
            return $this->notAuthorized();
        }

        $form->disconnect();

        return response()->json([
            'message' => trans('refactor/forms_builder.disconnected'),
        ]);
    }

    public function settings(Request $request, $uid)
    {
        $form = Form::findByUid($uid);

        if (!$form || Gate::denies('update', $form)) {
            return $this->notAuthorized();
        }

        $form->saveSettingsFromArray($request->all());

        return response()->json([
            'message' => trans('refactor/forms_builder.settings_saved'),
            'name' => $form->name,
        ]);
    }

    public function builderSave(\App\Http\Requests\Refactor\SaveFormBuilderRequest $request, $uid)
    {
        // Authorization + JSON structural rules already enforced by SaveFormBuilderRequest.
        // On failure Laravel returns 422 with { message, errors: { key: [messages] } }.
        $form = Form::findByUid($uid);

        $form->setTemplateContent($request->input('content'), $request->input('json'));

        return response()->json([
            'status' => 'success',
        ]);
    }

    public function changeTemplate(Request $request, $uid)
    {
        $form = Form::findByUid($uid);

        if (!$form || Gate::denies('update', $form)) {
            return $this->notAuthorized();
        }

        $template = \App\Model\Template::findByUid($request->template_uid);
        $form->changeTemplate($template);

        return response()->json([
            'status' => 'success',
        ]);
    }

    public function previewSave(Request $request, $uid)
    {
        $form = Form::findByUid($uid);

        if (!$form || Gate::denies('read', $form)) {
            return $this->notAuthorized();
        }

        $request->session()->put('form-preview-content-' . $form->uid, $request->content);

        return response()->json(['status' => 'ok']);
    }
}