File: /home/xedaptot/ai.naniguide.com/database/seeders/Demo/Stage09_TemplatesSeeder.php
<?php
namespace Database\Seeders\Demo;
use App\Model\AdCreative;
use App\Model\AdTemplate;
use App\Model\CustomerEmailTemplate;
use App\Model\FormTemplate;
use App\Model\SystemEmailTemplate;
use App\Model\Template;
use App\Services\TemplateService;
use Illuminate\Support\Str;
use Database\Seeders\TemplateSeeder;
/**
* Stage 09 — per-customer saved email templates.
*
* Copies from SystemEmailTemplate (canonical designs seeded by TemplateSeeder)
* into CustomerEmailTemplate for each demo customer.
*
* IMPORTANT: Only picks from SystemEmailTemplate, NOT from the global Template
* pool — that pool contains thousands of campaign-created copies with ugly
* names like "[Campaign: 69d5fae368691]" which should never appear in
* a customer's saved templates list.
*/
class Stage09_TemplatesSeeder extends AbstractDemoSeeder
{
protected int $fakerOffset = 9;
public function run(): void
{
$f = $this->faker();
// Source: only canonical system email templates (Blank, Minimal, Gallery, etc.)
$systemTemplates = SystemEmailTemplate::with('template')->get()->filter(fn ($s) => $s->template !== null);
if ($systemTemplates->isEmpty()) {
$this->log('no system email templates found — running TemplateSeeder to seed them');
try {
(new TemplateSeeder())->run();
$systemTemplates = SystemEmailTemplate::with('template')->get()->filter(fn ($s) => $s->template !== null);
} catch (\Throwable $e) {
$this->log('could not seed templates: ' . $e->getMessage());
return;
}
}
if ($systemTemplates->isEmpty()) {
$this->log('still no system email templates — skipping');
return;
}
$customers = Stage03_CustomersSeeder::$created;
$totalSaved = 0;
foreach ($customers as $customerKey => $customer) {
$count = $f->numberBetween(3, min(6, $systemTemplates->count()));
$picks = $systemTemplates->random($count);
foreach ($picks as $sysTemplate) {
// TemplateService::setTemplate() associates template_id and saves the
// subject — do NOT save $cet manually, template_id is NOT NULL.
$cet = new CustomerEmailTemplate();
$cet->customer_id = $customer->id;
TemplateService::for($cet)->setTemplate($sysTemplate->template, $sysTemplate->name);
$totalSaved++;
}
$this->log("customer {$customerKey}: {$count} saved templates");
}
$this->log("seeded {$totalSaved} customer email templates from " . $systemTemplates->count() . " system designs");
// Form templates: seed canonical Popup form templates if missing
if (FormTemplate::count() === 0) {
$this->log('no form templates — running TemplateSeeder::resetFormTemplates()');
try {
(new TemplateSeeder())->resetFormTemplates();
$this->log('seeded ' . FormTemplate::count() . ' canonical form templates');
} catch (\Throwable $e) {
$this->log('could not auto-seed form templates: ' . $e->getMessage());
}
}
// Ad templates are seeded by Stage22_AdsSeeder, which reads sample JSON
// + SVG thumbnails from resources/themes/default/master/sample/ads/
// (one-way synced from builderjs via copy.sh). Do not inline ad content
// arrays here — see docs/builderjs-integration/BUILDER_CONNECT.md "Sample Templates +
// Thumbnails — ONE-WAY RULE".
// Ad creatives — give primary customer 2 realistic creatives so the
// creatives listing + overview card show content on the demo site.
$primaryCustomer = $customers['primary'] ?? reset($customers);
if ($primaryCustomer && AdCreative::where('customer_id', $primaryCustomer->id)->count() === 0) {
$this->seedAdCreativesForCustomer($primaryCustomer);
}
}
/**
* Seed 2 ad creatives for the primary demo customer so the listing +
* campaign overview preview show meaningful content on the demo site.
*
* Reads builder_content from the shipped sample JSONs on disk. No inline
* PHP content arrays — see docs/builderjs-integration/BUILDER_CONNECT.md "Sample Templates +
* Thumbnails — ONE-WAY RULE".
*/
protected function seedAdCreativesForCustomer($customer): void
{
$base = resource_path('themes/default/master/sample/ads');
$loadSample = function (string $file) use ($base): ?array {
$path = $base . '/' . $file . '.json';
if (!is_file($path)) return null;
$decoded = json_decode((string) file_get_contents($path), true);
return is_array($decoded) ? $decoded : null;
};
$creatives = [
[
'name' => 'Summer Sale — Meta Feed',
'type' => AdCreative::TYPE_IMAGE,
'headline' => 'Unlock 30% off your first order',
'primary_text' => 'Join thousands of happy customers. Limited time offer — tap Shop Now to claim yours today.',
'description' => 'Limited time',
'call_to_action' => 'shop_now',
'destination_url' => 'https://example.com/summer-sale',
'image_url' => 'https://images.unsplash.com/photo-1556742049-0cfed4f6a45d?w=1080&h=1080&fit=crop',
'sample_file' => 'FacebookFeed',
],
[
'name' => 'Spring Collection — Instagram',
'type' => AdCreative::TYPE_IMAGE,
'headline' => 'Style that speaks for itself',
'primary_text' => 'Discover the new collection — crafted for everyday confidence.',
'description' => 'Shop the look',
'call_to_action' => 'shop_now',
'destination_url' => 'https://example.com/spring',
'image_url' => 'https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=1080&h=1080&fit=crop',
'sample_file' => 'InstagramStory',
],
];
foreach ($creatives as $data) {
AdCreative::create([
'uid' => Str::random(32),
'customer_id' => $customer->id,
'name' => $data['name'],
'type' => $data['type'],
'headline' => $data['headline'],
'primary_text' => $data['primary_text'],
'description' => $data['description'],
'call_to_action' => $data['call_to_action'],
'destination_url' => $data['destination_url'],
'image_url' => $data['image_url'],
'builder_content' => $loadSample($data['sample_file']),
]);
}
$this->log('seeded 2 ad creatives for primary customer');
}
}