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/database/seeders/Demo/Stage17_WebsitesSeeder.php
<?php

namespace Database\Seeders\Demo;

use App\Model\Form;
use App\Model\Website;

/**
 * Stage 17 — Websites (WordPress integrations).
 */
class Stage17_WebsitesSeeder extends AbstractDemoSeeder
{
    protected int $fakerOffset = 17;

    public function run(): void
    {
        if (!class_exists(Website::class)) {
            $this->log('Website model missing — skipping');
            return;
        }
        $f = $this->faker();
        $customers = Stage03_CustomersSeeder::$created;
        $created = 0;

        foreach (DemoConfig::customers() as $cfg) {
            $customer = $customers[$cfg['key']] ?? null;
            if (!$customer) continue;
            for ($i = 0; $i < ($cfg['websites'] ?? 0); $i++) {
                $w = new Website();
                $w->customer_id = $customer->id;
                $w->title       = $cfg['company'] . ($i > 0 ? ' Blog #' . ($i + 1) : '');
                $w->url         = 'https://' . preg_replace('/[^a-z0-9]/', '', strtolower($cfg['company'])) . '.demo' . ($i > 0 ? '/blog' : '');
                $w->status      = $f->randomElement(['active', 'active', 'pending']);
                $w->metadata    = json_encode([
                    'platform' => $f->randomElement(['wordpress', 'shopify', 'ghost']),
                    'version'  => '6.4.2',
                ]);
                $w->save();
                $created++;

                // Link the customer's first form to this website and flip it to
                // STATUS_PUBLISHED so the frontend connect-js endpoint returns a
                // live AFormPopup bundle. The embedded-popup e2e test relies on
                // the first Website having at least one published, populated
                // form attached.
                $form = Form::where('customer_id', $customer->id)->first();
                if ($form) {
                    $meta = [];
                    if (!empty($form->metadata)) {
                        $decoded = json_decode($form->metadata, true);
                        if (is_array($decoded)) $meta = $decoded;
                    }
                    $meta['website_uid'] = $w->uid;
                    $form->metadata = json_encode($meta);
                    $form->status = Form::STATUS_PUBLISHED;
                    $form->save();

                    // Templates ship with an EMPTY FormContainerCell placeholder —
                    // BuilderJS only emits the `<form data-form-container-wrapper>`
                    // tag when FCC has child blocks, and we don't run BuilderJS at
                    // seed time. Inject a populated FCC (matching what a saved
                    // form would produce) so frontend popup rendering has a real
                    // form to claim. Only runs once per template.
                    $this->populateFormContainerCell($form);
                }
            }
        }
        $this->log("seeded {$created} websites");

        // Materialise public/form_test.html pointing at the first demo Website
        // so the embedded-popup + form-settings e2e tests can load the host
        // page without any extra setup step.
        $this->writeFormTestHost();
    }

    private function writeFormTestHost(): void
    {
        $w = Website::first();
        if (!$w) return;
        $base = rtrim(config('app.url') ?: url('/'), '/');
        $html = <<<HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Form embed test</title>
</head>
<body>
    <h1>Hello</h1>
    <button id="demo-popup-trigger" type="button">Open popup</button>
    <script id="ACXConnectScript" type="text/javascript" src="{$base}/rui/websites/{$w->uid}/connect-js"></script>
</body>
</html>

HTML;
        $path = public_path('form_test.html');
        if (is_dir(dirname($path))) {
            @file_put_contents($path, $html);
            $this->log('wrote public/form_test.html → website ' . $w->uid);
        }
    }

    private function populateFormContainerCell(Form $form): void
    {
        $template = $form->template;
        if (!$template || empty($template->content)) return;
        $html = $template->content;
        if (strpos($html, 'data-form-container-wrapper') !== false) return;

        // Find the first `<div builder-element="FormContainerCell" ...>...</div>`
        // block and replace its body (empty drop placeholder) with a wrapped form.
        $replacement = '<form action="" method="post" data-form-container-wrapper="1" style="padding:0;margin:0">'
            . '<div class="form-group" style="margin-bottom:16px"><label for="f-email" style="display:block;margin-bottom:6px;font-weight:500">Email</label>'
            . '<input id="f-email" type="email" name="EMAIL" class="form-control" required style="width:100%;padding:10px;border:1px solid #d1d5db;border-radius:6px"></div>'
            . '<div class="form-group" style="margin-bottom:16px"><label for="f-first" style="display:block;margin-bottom:6px;font-weight:500">First name</label>'
            . '<input id="f-first" type="text" name="FIRST_NAME" class="form-control" style="width:100%;padding:10px;border:1px solid #d1d5db;border-radius:6px"></div>'
            . '<button type="submit" class="btn btn-primary" style="width:100%;padding:12px;background:#6366f1;color:#fff;border:0;border-radius:6px;font-weight:600">Subscribe</button>'
            . '</form>';

        $pattern = '/(<div builder-element="FormContainerCell"[^>]*>)(.*?)(<\/div>\s*<\/div>\s*<\/div>)/s';
        $rewritten = preg_replace_callback($pattern, function ($m) use ($replacement) {
            return $m[1] . $replacement . '</div></div></div>';
        }, $html, 1);

        if ($rewritten && $rewritten !== $html) {
            $template->content = $rewritten;
            $template->save();
        }
    }
}