oont-contents/plugins/mailpoet/lib/Automation/Integrations/MailPoet/Templates/EmailFactory.php
2025-04-06 08:34:48 +02:00

262 lines
8.1 KiB
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\Entities\NewsletterEntity;
use MailPoet\Entities\NewsletterOptionEntity;
use MailPoet\Entities\NewsletterOptionFieldEntity;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository;
use MailPoet\Newsletter\Options\NewsletterOptionsRepository;
use MailPoet\Settings\SettingsController;
use MailPoet\Util\Security;
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;
public function __construct(
NewslettersRepository $newslettersRepository,
SettingsController $settings,
WordPress $wp,
NewsletterOptionsRepository $newsletterOptionsRepository,
NewsletterOptionFieldsRepository $newsletterOptionFieldsRepository
) {
$this->newslettersRepository = $newslettersRepository;
$this->settings = $settings;
$this->wp = $wp;
$this->newsletterOptionsRepository = $newsletterOptionsRepository;
$this->newsletterOptionFieldsRepository = $newsletterOptionFieldsRepository;
}
/**
* 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 {
// Create a new newsletter entity
$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());
// 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();
}
/**
* 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);
}
/**
* 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';
}
}