diff --git a/db/migrations/20261016150000_create_newsletter_drafts.php b/db/migrations/20261016150000_create_newsletter_drafts.php new file mode 100644 index 0000000..62b2dfe --- /dev/null +++ b/db/migrations/20261016150000_create_newsletter_drafts.php @@ -0,0 +1,47 @@ +table('newsletter_drafts', ['id' => 'iddraft']) + ->addColumn('title', 'string', ['limit' => 255, 'default' => '']) + ->addColumn('subject', 'string', ['limit' => 255, 'default' => '']) + ->addColumn('preheader', 'string', ['limit' => 255, 'default' => '']) + ->addColumn('blocks', 'text', ['limit' => \Phinx\Db\Adapter\MysqlAdapter::TEXT_LONG, 'null' => true]) + ->addColumn('settings', 'text', ['limit' => \Phinx\Db\Adapter\MysqlAdapter::TEXT_LONG, 'null' => true]) + ->addColumn('revision', 'integer', ['default' => 0, 'signed' => false]) + ->addColumn('wp_email_id', 'integer', ['null' => true]) + ->addColumn('wp_pushed_at', 'datetime', ['null' => true]) + ->addColumn('created_by', 'integer', ['signed' => false, 'default' => 0]) + ->addColumn('updated_by', 'integer', ['signed' => false, 'default' => 0]) + ->addColumn('created_at', 'datetime') + ->addColumn('updated_at', 'datetime') + ->addColumn('deleted_at', 'datetime', ['null' => true]) + ->addColumn('idschool', 'integer', ['signed' => false, 'default' => 1]) + ->addIndex(['updated_at']) + ->addIndex(['idschool']) + ->create(); + + $this->table('newsletter_draft_versions', ['id' => 'idversion']) + ->addColumn('iddraft', 'integer') + ->addColumn('revision', 'integer', ['signed' => false, 'default' => 0]) + ->addColumn('subject', 'string', ['limit' => 255, 'default' => '']) + ->addColumn('preheader', 'string', ['limit' => 255, 'default' => '']) + ->addColumn('blocks', 'text', ['limit' => \Phinx\Db\Adapter\MysqlAdapter::TEXT_LONG, 'null' => true]) + ->addColumn('settings', 'text', ['limit' => \Phinx\Db\Adapter\MysqlAdapter::TEXT_LONG, 'null' => true]) + ->addColumn('note', 'string', ['limit' => 100, 'default' => '']) + ->addColumn('created_by', 'integer', ['signed' => false, 'default' => 0]) + ->addColumn('created_at', 'datetime') + ->addIndex(['iddraft', 'created_at']) + ->create(); + } +} diff --git a/public/class/NewsletterRenderer.php b/public/class/NewsletterRenderer.php new file mode 100644 index 0000000..dde19ef --- /dev/null +++ b/public/class/NewsletterRenderer.php @@ -0,0 +1,658 @@ + '#f4f4f4', + 'block_background' => '#ffffff', + 'font_family' => 'Verdana, Geneva, sans-serif', + 'font_size' => 16, + 'text_color' => '#222222', + 'link_color' => '#007bff', + 'title_font_size' => 28, + 'title_color' => '#222222', + 'button_background' => '#256f9c', + 'button_color' => '#ffffff', + 'social' => [ + 'facebook' => 'https://www.facebook.com/yogasoul.it/', + 'instagram' => 'https://www.instagram.com/aura_yogasoul/', + 'youtube' => 'https://www.youtube.com/@yogasoul6746', + 'whatsapp' => 'https://wa.me/393534982534', + ], + ]; + } + + /** Blocchi di una newsletter nuova. */ + public static function starterBlocks(): array + { + return [ + self::newBlock('header'), + self::newBlock('text', ['html' => '
come stai?
Scrivi qui il testo della newsletter…
']), + self::newBlock('image'), + self::newBlock('button'), + self::newBlock('separator'), + self::newBlock('social'), + self::newBlock('footer'), + ]; + } + + /** Valori predefiniti per tipo di blocco. */ + public static function newBlock(string $type, array $values = []): array + { + $defaults = [ + 'header' => ['logo_url' => 'https://yogasoul.it/wp-content/uploads/2025/01/Logo-YogaSoul_parziale-1.png', 'logo_width' => 80, 'link' => 'https://yogasoul.it', 'pad_top' => 24, 'pad_bottom' => 24], + 'heading' => ['text' => 'Titolo', 'align' => 'center', 'font_size' => '', 'color' => '', 'background' => '', 'pad_top' => 30, 'pad_bottom' => 10], + 'text' => ['html' => 'Testo…
', 'background' => '', 'background_2' => '', 'pad_top' => 20, 'pad_bottom' => 20], + 'image' => ['url' => '', 'alt' => '', 'link' => '', 'width' => 600, 'pad_top' => 0, 'pad_bottom' => 0], + 'button' => ['label' => 'Prenota la tua lezione', 'url' => 'https://yogasoul.it', 'button_bg' => '', 'color' => '', 'font_size' => 20, 'width' => 300, 'radius' => 6, 'pad_top' => 20, 'pad_bottom' => 20], + 'columns' => ['image_url' => '', 'image_alt' => '', 'link' => '', 'image_side' => 'left', 'html' => 'Testo accanto all\'immagine…
', 'pad_top' => 20, 'pad_bottom' => 20], + 'separator' => ['color' => '#dddddd', 'height' => 1, 'pad_top' => 20, 'pad_bottom' => 20], + 'social' => ['icon_size' => 32, 'pad_top' => 15, 'pad_bottom' => 15], + 'footer' => ['profile_label' => "Modifica l'iscrizione", 'view_label' => 'Vedi online', 'unsub_label' => 'Disiscriviti', 'pad_top' => 15, 'pad_bottom' => 15], + 'raw' => ['html' => '', 'wp_id' => ''], + ]; + + return array_merge( + ['id' => bin2hex(random_bytes(6)), 'type' => $type], + $defaults[$type] ?? [], + $values + ); + } + + /* ===================================================================== + * Rendering + * ===================================================================== */ + + /** + * HTML completo della newsletter. + * $forPreview = true sostituisce i tag del plugin con valori di esempio. + */ + public static function renderDocument(array $blocks, array $settings, string $subject, string $preheader, bool $forPreview = false): string + { + $s = self::settings($settings); + + $head = file_get_contents(__DIR__ . '/newsletter_head.html'); + $head = str_replace('{{LINK_COLOR}}', self::color($s['link_color'], '#007bff'), $head); + + $body = ''; + foreach ($blocks as $b) { + if (is_array($b) && isset($b['type'])) { + $body .= self::renderBlock($b, $s) . "\n"; + } + } + + $bg = self::color($s['background'], '#f4f4f4'); + + $html = $head + . '' . "\n" + . '\n\n" + . "| " + . $body + . "\n | \n