FileMaster
Search
Toggle Dark Mode
Home
/
.
/
wp-content
/
plugins
/
mailpoet
/
lib
/
Automation
/
Integrations
/
MailPoet
/
Templates
Edit File: EmailFactory.php
<?php declare(strict_types = 1); namespace MailPoet\Automation\Integrations\MailPoet\Templates; if (!defined('ABSPATH')) exit; use MailPoet\Automation\Engine\Data\Automation; use MailPoet\Automation\Engine\Exceptions\NotFoundException; use MailPoet\Automation\Engine\WordPress; use MailPoet\Config\Env; use MailPoet\EmailEditor\Integrations\MailPoet\EmailEditor; use MailPoet\EmailEditor\Integrations\MailPoet\Patterns\PatternsController; use MailPoet\EmailEditor\Integrations\MailPoet\Templates\TemplatesController; use MailPoet\Entities\NewsletterEntity; use MailPoet\Entities\NewsletterOptionEntity; use MailPoet\Entities\NewsletterOptionFieldEntity; use MailPoet\Entities\WpPostEntity; use MailPoet\Newsletter\NewslettersRepository; use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository; use MailPoet\Newsletter\Options\NewsletterOptionsRepository; use MailPoet\Settings\SettingsController; use MailPoet\Util\Security; use MailPoet\WP\Functions as WPFunctions; use MailPoetVendor\Doctrine\ORM\EntityManager; class EmailFactory { /** @var NewslettersRepository */ private $newslettersRepository; /** @var SettingsController */ private $settings; /** @var string|null */ protected $templatesDirectory; /** @var WordPress */ private $wp; /** @var NewsletterOptionsRepository */ private $newsletterOptionsRepository; /** @var NewsletterOptionFieldsRepository */ private $newsletterOptionFieldsRepository; private PatternsController $patternsController; private TemplatesController $templatesController; private EntityManager $entityManager; private WPFunctions $wpFunctions; public function __construct( NewslettersRepository $newslettersRepository, SettingsController $settings, WordPress $wp, NewsletterOptionsRepository $newsletterOptionsRepository, NewsletterOptionFieldsRepository $newsletterOptionFieldsRepository, PatternsController $patternsController, TemplatesController $templatesController, WPFunctions $wpFunctions, EntityManager $entityManager ) { $this->newslettersRepository = $newslettersRepository; $this->settings = $settings; $this->wp = $wp; $this->newsletterOptionsRepository = $newsletterOptionsRepository; $this->newsletterOptionFieldsRepository = $newsletterOptionFieldsRepository; $this->patternsController = $patternsController; $this->templatesController = $templatesController; $this->entityManager = $entityManager; $this->wpFunctions = $wpFunctions; } /** * Create an email from a template and store it in the database * * @param array $data Email data including subject, preheader, etc. * @return int|null The ID of the created email or null if the email couldn't be created */ public function createEmail(array $data = []): ?int { $newsletter = $this->createNewsletterEntity($data); // Set content if provided if (isset($data['content'])) { $newsletter->setBody($data['content']); } elseif (isset($data['template'])) { $template = $this->loadTemplate($data['template']); if ($template) { $newsletter->setBody($template); } } // Save the newsletter to the database $this->newslettersRepository->persist($newsletter); $this->newslettersRepository->flush(); // Return the newsletter ID return $newsletter->getId(); } /** * Create a block editor email from a pattern and store it in the database. * * This method creates a WordPress post with the pattern content and links it * to a NewsletterEntity for use with the block email editor. * * @param array $data Email data including: * - 'pattern' (string, required): The pattern name (e.g., 'welcome-email-content') * - 'subject' (string, optional): Email subject * - 'preheader' (string, optional): Email preheader * - 'sender_name' (string, optional): Sender name * - 'sender_address' (string, optional): Sender email address * @param string|null $templateSlug The slug of the template to associate with the email. * @return array{email_id: int, email_wp_post_id: int}|null The IDs of the created email and WP post, or null if creation failed */ public function createBlockEditorEmail(array $data, ?string $templateSlug = null): ?array { $patternName = $data['pattern'] ?? null; if (!$patternName) { return null; } // Get pattern content $patternContent = $this->patternsController->getPatternContent($patternName); if ($patternContent === null) { return null; } // Create a WordPress post with the pattern content // The meta_input flag prevents other plugins from creating duplicate newsletters // Automation emails use 'private' status to prevent them from appearing in public queries $postId = $this->wpFunctions->wpInsertPost([ 'post_content' => $patternContent, 'post_type' => EmailEditor::MAILPOET_EMAIL_POST_TYPE, 'post_status' => 'private', 'post_author' => $this->wpFunctions->getCurrentUserId(), 'post_title' => $data['subject'] ?? __('New Email', 'mailpoet'), 'meta_input' => ['_mailpoet_is_automation_email' => '1'], ]); if (!is_int($postId) || $postId <= 0) { return null; } // Set the email template to associate the template wrapper (header, footer, unsubscribe links) $templateSlug = $templateSlug ?: $this->templatesController->getDefaultTemplateSlug(); $this->wpFunctions->updatePostMeta($postId, '_wp_page_template', $templateSlug); // Create a new newsletter entity try { $wpPost = $this->entityManager->getReference(WpPostEntity::class, $postId); $newsletter = $this->createNewsletterEntity($data, $wpPost); $this->newslettersRepository->persist($newsletter); $this->newslettersRepository->flush(); } catch (\Throwable $e) { $this->wpFunctions->wpDeletePost($postId, true); throw $e; } $emailId = $newsletter->getId(); if ($emailId === null) { $this->wpFunctions->wpDeletePost($postId, true); return null; } return [ 'email_id' => $emailId, 'email_wp_post_id' => $postId, ]; } /** * Sets automation and step ID for all email steps in an automation * * @param Automation $automation The automation object * @return void */ public function setAutomationIdForEmails(Automation $automation): void { // Skip if automation ID is not set try { $automationId = $automation->getId(); } catch (\Exception $e) { return; } $steps = $automation->getSteps(); $emailSteps = array_filter($steps, function($step) { return $step->getKey() === 'mailpoet:send-email'; }); foreach ($emailSteps as $step) { $args = $step->getArgs(); $emailId = $args['email_id'] ?? null; if ($emailId) { $newsletter = $this->newslettersRepository->findOneById($emailId); if (!$newsletter) { continue; } $existingAutomationId = $newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_AUTOMATION_ID); $existingStepId = $newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_AUTOMATION_STEP_ID); if ($existingAutomationId === (string)$automationId && $existingStepId === $step->getId()) { continue; } $this->storeNewsletterOption( $newsletter, NewsletterOptionFieldEntity::NAME_AUTOMATION_ID, (string)$automationId ); $this->storeNewsletterOption( $newsletter, NewsletterOptionFieldEntity::NAME_AUTOMATION_STEP_ID, $step->getId() ); $this->newslettersRepository->flush(); } } } /** * Stores a newsletter option * * @param NewsletterEntity $newsletter The newsletter entity * @param string $optionName The name of the option * @param string|null $optionValue The value of the option * @return void */ private function storeNewsletterOption(NewsletterEntity $newsletter, string $optionName, ?string $optionValue = null): void { if (!$optionValue || !$this->newsletterOptionsRepository || !$this->newsletterOptionFieldsRepository) { return; } $existingOption = $newsletter->getOption($optionName); if ($existingOption && $existingOption->getValue() === $optionValue) { return; // Skip if option already exists with the same value } $field = $this->newsletterOptionFieldsRepository->findOneBy([ 'name' => $optionName, 'newsletterType' => $newsletter->getType(), ]); if (!$field) { return; } // If option exists but with different value, update it if ($existingOption) { $existingOption->setValue($optionValue); return; } // Otherwise create a new option $option = new NewsletterOptionEntity($newsletter, $field); $option->setValue($optionValue); $this->newsletterOptionsRepository->persist($option); $newsletter->getOptions()->add($option); } /** * Create a NewsletterEntity with common automation email properties. * * @param array $data Email data including subject, preheader, sender_name, sender_address * @param WpPostEntity|null $wpPost Optional WP post to associate with the newsletter * @return NewsletterEntity The created newsletter entity (not persisted) */ private function createNewsletterEntity(array $data, ?WpPostEntity $wpPost = null): NewsletterEntity { $newsletter = new NewsletterEntity(); $newsletter->setType(NewsletterEntity::TYPE_AUTOMATION); $newsletter->setStatus(NewsletterEntity::STATUS_ACTIVE); $newsletter->setSubject($data['subject'] ?? ''); $newsletter->setPreheader($data['preheader'] ?? ''); $newsletter->setSenderName($data['sender_name'] ?? $this->getDefaultSenderName()); $newsletter->setSenderAddress($data['sender_address'] ?? $this->getDefaultSenderAddress()); $newsletter->setHash(Security::generateHash()); if ($wpPost !== null) { $newsletter->setWpPost($wpPost); } return $newsletter; } /** * Get the default sender name from settings */ private function getDefaultSenderName(): string { return $this->settings->get('sender.name', ''); } /** * Get the default sender address from settings */ private function getDefaultSenderAddress(): string { return $this->settings->get('sender.address', ''); } /** * Load a template from a file * * @param string $templateName The name of the template file (without .json extension) * @return array|null The template body or null if the template doesn't exist */ public function loadTemplate(string $templateName): ?array { $templatePath = $this->getTemplatePath($templateName); if (!file_exists($templatePath)) { throw new NotFoundException('Template not found: ' . $templateName); } return $this->fetchEmailTemplate($templatePath); } /** * Get the path to a template file * * @param string $templateName The name of the template file (without .json extension) * @return string The full path to the template file */ protected function getTemplatePath(string $templateName): string { $sanitizedTemplateName = $this->wp->sanitizeFileName($templateName); return $this->getTemplatesDirectory() . '/' . $sanitizedTemplateName . '.json'; } /** * Fetch email template from a file * * @param string $templatePath The path to the template file * @return array|null The template body or null if the template couldn't be loaded */ private function fetchEmailTemplate(string $templatePath): ?array { $templateString = file_get_contents($templatePath); if ($templateString === false) { return null; } $templateArr = json_decode((string)$templateString, true); if (!is_array($templateArr) || !isset($templateArr['body'])) { return null; } return $templateArr['body']; } /** * Set the templates directory * * @param string|null $directory The directory where templates are stored * @return self */ public function setTemplatesDirectory(?string $directory): self { $this->templatesDirectory = $directory; return $this; } /** * Get the templates directory * * @return string The directory where templates are stored */ public function getTemplatesDirectory(): string { return $this->templatesDirectory ?: Env::$libPath . '/Automation/Integrations/MailPoet/Templates/EmailTemplates'; } }
Save
Back