File: /home/xedaptot/ai.naniguide.com/app/Http/Controllers/FormController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Model\Form;
use App\Model\Template;
use App\Model\MailList;
use App\Model\FormTemplate;
use App\Services\SubscriberService;
class FormController extends Controller
{
public function index(Request $request)
{
// authorize
if (\Gate::denies('list', Form::class)) {
return $this->notAuthorized();
}
return view('forms.index');
}
public function create(Request $request)
{
$form = Form::newDefault($request->user()->customer);
// authorize
if (\Gate::denies('create', Form::class)) {
return $this->notAuthorized();
}
if ($request->isMethod('post')) {
$validator = $form->createFromArray($request->all());
// redirect if fails
if ($validator->fails()) {
return response()->view('forms.create', [
'form' => $form,
'errors' => $validator->errors(),
], 400);
}
return redirect()->action('FormController@build', [
'uid' => $form->uid,
])->with('alert-success', trans('messages.form.created', [
'name' => $form->name,
]));
}
return view('forms.create', [
'form' => $form,
]);
}
public function templates(Request $request)
{
// authorize
if (\Gate::denies('create', Form::class)) {
return $this->notAuthorized();
}
$formTemplates = FormTemplate::query()
->search($request->keyword)
->orderBy($request->sort_order, $request->sort_direction)
->paginate(8);
return view('forms.templates', [
'formTemplates' => $formTemplates,
]);
}
public function list(Request $request)
{
// authorize
if (\Gate::denies('list', Form::class)) {
return $this->notAuthorized();
}
// sort, pagination
$forms = $request->user()->customer->local()->forms()->search($request->keyword)
->filter($request->all())
->orderBy($request->sort_order, $request->sort_direction)
->paginate($request->per_page);
return view('forms.list', [
'forms' => $forms,
]);
}
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) {
// authorize
if ($request->user()->customer->can('delete', $form)) {
$form->delete();
$deleted += 1;
}
}
return response()->json([
'message' => trans('messages.forms.deleted', [ 'deleted' => $deleted, 'total' => $total]),
]);
}
public function build(Request $request)
{
$form = Form::findByUid($request->uid);
// authorize
if (\Gate::denies('update', $form)) {
return $this->notAuthorized();
}
$formTemplates = FormTemplate::get();
return view('forms.build', [
'form' => $form,
'templates' => $formTemplates->map(function ($formTemplate) {
return $formTemplate->template;
}),
]);
}
public function builderContent(Request $request)
{
// Generate info
$form = Form::findByUid($request->uid);
// authorize
if (\Gate::denies('update', $form)) {
return $this->notAuthorized();
}
$content = view('forms.content', [
'template' => $form->template,
'content' => $form->template->content,
]);
return response($content)->header('Access-Control-Allow-Origin', '*');
}
public function builder(Request $request)
{
$form = Form::findByUid($request->uid);
// authorize
if (\Gate::denies('update', $form)) {
return $this->notAuthorized();
}
// form fields for Editor
$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();
return view('forms.builder', [
'form' => $form,
'template' => $form->template,
'formFields' => $formFields,
'customer' => $form->customer,
]);
}
public function frontendContent(Request $request)
{
// Generate info
$form = Form::findByUid($request->uid);
// Language for frontend
$this->frontendLanguage($form);
if ($request->preview) {
$html = $request->session()->get('form-preview-content-' . $form->uid);
$content = $form->renderedContent($html);
} else {
$content = $form->renderedContent();
}
$content = view('forms.frontend.content', [
'form' => $form,
'content' => $content,
]);
return response($content)->header('Access-Control-Allow-Origin', '*');
}
public function preview(Request $request)
{
$form = Form::findByUid($request->uid);
// authorize
if (\Gate::denies('read', $form)) {
return $this->notAuthorized();
}
$request->session()->put('form-preview-content-' . $form->uid, $request->content);
}
public function frontendPopup(Request $request)
{
$form = Form::findByUid($request->uid);
// Language for frontend
$this->frontendLanguage($form);
$content = view('forms.frontend.popup', [
'form' => $form,
]);
return response($content)
->header('Access-Control-Allow-Origin', '*')
->header('Content-Type', 'application/javascript');
}
public function settings(Request $request)
{
$form = Form::findByUid($request->uid);
// authorize
if (\Gate::denies('update', $form)) {
return $this->notAuthorized();
}
try {
$form->saveSettingsFromArray($request->all());
return response()->json([
'message' => trans('messages.form.settins_saved'),
]);
} catch (\Exception $e) {
return response()->json([
'error' => $e->getMessage(),
], 400);
}
}
public function connect(Request $request)
{
$form = Form::findByUid($request->uid);
// authorize
if (\Gate::denies('update', $form)) {
return $this->notAuthorized();
}
if ($request->isMethod('post')) {
// make validator
$validator = \Validator::make($request->all(), [
'website_uid' => 'required',
]);
// redirect if fails
if ($validator->fails()) {
return response()->view('forms.connect', [
'form' => $form,
'errors' => $validator->errors(),
], 400);
}
$site = \App\Model\Website::findByUid($request->website_uid);
$form->connect($site);
return response()->json([
'message' => trans('messages.form.connected', [
'site' => $site->title,
]),
]);
}
return view('forms.connect', [
'form' => $form,
]);
}
public function disconnect(Request $request)
{
$form = Form::findByUid($request->uid);
// authorize
if (\Gate::denies('update', $form)) {
return $this->notAuthorized();
}
if ($request->isMethod('post')) {
$form->disconnect();
return response()->json([
'message' => trans('messages.form.disconnected'),
]);
}
return view('forms.connect', [
'form' => $form,
]);
}
public function publish(Request $request)
{
$forms = Form::whereIn(
'uid',
is_array($request->uids) ? $request->uids : explode(',', $request->uids)
);
$total = $forms->count();
$done = 0;
foreach ($forms->get() as $form) {
// authorize
if ($request->user()->customer->can('publish', $form)) {
$form->publish();
$done += 1;
}
}
return response()->json([
'status' => 'success',
'message' => trans('messages.forms.published', [ 'done' => $done, 'total' => $total]),
]);
}
public function unpublish(Request $request)
{
$forms = Form::whereIn(
'uid',
is_array($request->uids) ? $request->uids : explode(',', $request->uids)
);
$total = $forms->count();
$done = 0;
foreach ($forms->get() as $form) {
// authorize
if ($request->user()->customer->can('unpublish', $form)) {
$form->unpublish();
$done += 1;
}
}
return response()->json([
'status' => 'success',
'message' => trans('messages.forms.unpublished', [ 'done' => $done, 'total' => $total]),
]);
}
public function frontendLanguage($form)
{
// Language
if ($form->customer && $form->customer->language) {
\App::setLocale($form->customer->language->code);
\Carbon\Carbon::setLocale($form->customer->language->code);
}
}
public function frontendSave(Request $request)
{
$subscriberService = app(SubscriberService::class);
$form = Form::findByUid($request->uid);
// Language for frontend
$this->frontendLanguage($form);
// Compliance gate — pre-flight, BEFORE optInFromPopupForm (which
// persists the subscriber inside MailList::subscribe). The service
// walks the saved JSON to enforce every `TermsOfServiceElement`
// with required=true and keeps tampered POSTs from creating
// subscribers. Lives in the service layer (App\Services\Forms\
// TermsAcceptanceService) so the Form model stays focused on
// persistence + relationships per the FormRequest → DTO → Service
// → Controller layering rule.
$termsErrors = app(\App\Services\Forms\TermsAcceptanceService::class)->check($form, $request);
if (!empty($termsErrors)) {
return response()->json($termsErrors, 400);
}
try {
[$validator, $subscriber] = $subscriberService->optInFromPopupForm($form, $request);
} catch (\Exception $e) {
return response()->json([
'error' => $e->getMessage(),
], 400);
}
// if fails
if ($validator->fails()) {
return response()->json($validator->errors(), 400);
}
// Plugin opt-in extension point (W3 messenger plugin: SMS / WhatsApp /
// Telegram double opt-in confirmation pages). First non-null return
// wins; null means no plugin took the redirect. See
// `docs/messenger/DESIGN.md §9.8` for the contract.
$response = ['message' => 'OK'];
$redirectUrl = collect(\App\Library\Facades\Hook::collect('form.post_optin_redirect', [$subscriber, $request]))
->first(fn ($value) => is_string($value) && $value !== '');
if (is_string($redirectUrl)) {
$response['redirect_url'] = $redirectUrl;
}
return response()->json($response);
}
public function changeTemplate(Request $request)
{
$form = Form::findByUid($request->uid);
$template = Template::findByUid($request->template_uid);
// authorize
if (\Gate::denies('update', $form)) {
return $this->notAuthorized();
}
$form->changeTemplate($template);
return response()->json([
'url' => action('FormController@builderContent', [
'uid' => $form->uid,
]),
'saveUrl' => action('TemplateController@builderEdit', [
'uid' => $form->template->uid,
]),
'uploadAssetUrl' => route('upload_media')
]);
}
public function builderSave(Request $request)
{
$form = Form::findByUid($request->uid);
$rules = array(
'content' => 'required',
'json' => 'required',
);
$validator = \Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json([
'message' => $validator->errors()->first(),
], 400);
}
$form->setTemplateContent($request->content, $request->json);
return response()->json([
'status' => 'success',
]);
}
}