Skip to content

Commit

Permalink
#7191 Separate email template installation from migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
NateWr committed Nov 30, 2022
1 parent 1127f89 commit a8bfeae
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 1 deletion.
88 changes: 87 additions & 1 deletion classes/install/Installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use PKP\db\DBDataXMLParser;
use PKP\facades\Locale;
use APP\facades\Repo;
use PKP\db\XMLDAO;
use PKP\file\FileManager;
use PKP\filter\FilterHelper;
use PKP\notification\PKPNotification;
Expand Down Expand Up @@ -104,6 +105,9 @@ class Installer
/** @var array List of migrations executed already */
public $migrations = [];

/** @var array List of email template variables to rename. App-specific */
protected $appEmailTemplateVariableNames = [];

/**
* Constructor.
*
Expand Down Expand Up @@ -728,6 +732,10 @@ public function setCurrentVersion($version)
/**
* For upgrade: install email templates and data
*
* @deprecated 3.4 Do not use <code function="installEmailTemplate" ...>
* in upgrade scripts to 3.4 and later versions. This is no longer in
* sync with the PKP\emailTemplates\DAO methods to install email templates.
*
* @param object $installer
* @param array $attr Attributes: array containing
* 'key' => 'EMAIL_KEY_HERE',
Expand All @@ -736,10 +744,88 @@ public function setCurrentVersion($version)
public function installEmailTemplate($installer, $attr)
{
$locales = explode(',', $attr['locales'] ?? '');
Repo::emailTemplate()->dao->installEmailTemplates(Repo::emailTemplate()->dao->getMainEmailTemplatesFilename(), $locales, $attr['key']);
$emailKey = $attr['key'] ?? '';

if (!$emailKey) {
throw new Exception('Tried to install email template but no template key provided.');
}

$xmlDao = new XMLDAO();
$data = $xmlDao->parseStruct('registry/emailTemplates.xml', ['email']);
if (!isset($data['email'])) {
return false;
}

if (empty($locales)) {
$siteDao = DAORegistry::getDAO('SiteDAO'); /** @var SiteDAO $siteDao */
$site = $siteDao->getSite(); /** @var Site $site */
$locales = $site->getInstalledLocales();
}

// filter out any invalid locales that is not supported by site
$allLocales = array_keys(Locale::getLocales());
if (!empty($invalidLocales = array_diff($locales, $allLocales))) {
$locales = array_diff($locales, $invalidLocales);
}

foreach ($data['email'] as $entry) {
$attrs = $entry['attributes'];
if ($emailKey && $emailKey != $attrs['key']) {
continue;
}
if (DB::table('email_templates_default_data')->where('email_key', $attrs['key'])->exists()) {
continue;
}

$subject = $attrs['subject'] ?? null;
$body = $attrs['body'] ?? null;
if ($subject && $body) {
foreach ($locales as $locale) {
DB::table('email_templates_default_data')
->where('email_key', $attrs['key'])
->where('locale', $locale)
->delete();

$previous = Locale::getMissingKeyHandler();
Locale::setMissingKeyHandler(fn (string $key): string => '');
$translatedSubject = __($subject, [], $locale);
$translatedBody = __($body, [], $locale);
Locale::setMissingKeyHandler($previous);
if ($translatedSubject !== null && $translatedBody !== null) {
DB::table('email_templates_default_data')->insert([
'email_key' => $attrs['key'],
'locale' => $locale,
'subject' => $this->renameEmailTemplateVariables($translatedSubject),
'body' => $this->renameEmailTemplateVariables($translatedBody),
]);
}
}
}
}

return true;
}

/**
* @deprecated 3.4
* @see self::installEmailTemplate()
*/
protected function renameEmailTemplateVariables($string): string
{
if (empty($this->appEmailTemplateVariableNames)) {
return $string;
}

$variables = [];
$replacements = [];
foreach ($this->appEmailTemplateVariableNames as $key => $value) {
$variables[] = '/\{\$' . $key . '\}/';
$replacements[] = '{$' . $value . '}';
}

return preg_replace($variables, $replacements, $string);
}

/**
* Install the given filter configuration file.
*
Expand Down
140 changes: 140 additions & 0 deletions classes/migration/upgrade/v3_4_0/InstallEmailTemplates.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<?php

/**
* @file classes/migration/upgrade/v3_4_0/InstallEmailTemplates.php
*
* Copyright (c) 2014-2022 Simon Fraser University
* Copyright (c) 2000-2022 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class InstallEmailTemplates
* @brief Install all new email templates for 3.4.
*/

namespace PKP\migration\upgrade\v3_4_0;

use APP\core\Services;
use Exception;
use Illuminate\Support\Facades\DB;
use PKP\db\XMLDAO;
use PKP\facades\Locale;
use PKP\migration\Migration;

abstract class InstallEmailTemplates extends Migration
{
protected array $emailTemplatesInstalled = [];

abstract protected function getEmailTemplateKeys(): array;
abstract protected function getAppVariableNames(): array;

public function up(): void
{
$xmlDao = new XMLDAO();

$data = $xmlDao->parseStruct('registry/emailTemplates.xml', ['email']);

if (!isset($data['email'])) {
throw new Exception('Unable to find <email> entries in registry/emailTemplates.xml.');
}

$contextIds = Services::get('context')->getIds();
$locales = json_decode(
DB::table('site')->pluck('installed_locales')->first()
);

foreach ($data['email'] as $entry) {

$attrs = $entry['attributes'];

if (!in_array($attrs['key'], $this->getEmailTemplateKeys())) {
continue;
}

if (DB::table('email_templates_default_data')->where('email_key', $attrs['key'])->exists()) {
continue;
}

$name = $attrs['name'] ?? null;
$subject = $attrs['subject'] ?? null;
$body = $attrs['body'] ?? null;

if (!$name || !$subject || !$body) {
throw new Exception('Failed to install email template ' . $attrs['key'] . '. Missing name, subject or body attribute.');
}

$previous = Locale::getMissingKeyHandler();
Locale::setMissingKeyHandler(fn (string $key): string => '');

foreach ($locales as $locale) {
$translatedName = $name ? __($name, [], $locale) : $attrs['key'];
$translatedSubject = __($subject, [], $locale);
$translatedBody = __($body, [], $locale);

DB::table('email_templates_default_data')->insert([
'email_key' => $attrs['key'],
'locale' => $locale,
'name' => $translatedName,
'subject' => $this->renameApplicationVariables($translatedSubject),
'body' => $this->renameApplicationVariables($translatedBody),
]);
}

$this->emailTemplatesInstalled[] = $attrs['key'];

Locale::setMissingKeyHandler($previous);

if (isset($attrs['alternateTo'])) {

$exists = DB::table('email_templates_default_data')
->where('email_key', $attrs['alternateTo'])
->exists();

if (!$exists) {
throw new Exception('Tried to install email template `' . $attrs['key'] . '` as an alternate to `' . $attrs['alternateTo'] . '`, but no default template exists with this key.');
}

foreach ($contextIds as $contextId) {
DB::table('email_templates')->insert([
'email_key' => $attrs['key'],
'context_id' => $contextId,
'alternate_to' => $attrs['alternateTo'],
]);
}
}
}
}

public function down(): void
{
DB::table('email_templates_default_data')
->whereIn('email_key', $this->emailTemplatesInstalled)
->delete();

DB::table('email_templates')
->whereIn('email_key', $this->emailTemplatesInstalled)
->delete();
}

/**
* Rename the email template variables that are app-specific
*
* @param string $string Email template subject or body to be modified
*/
protected function renameApplicationVariables(string $string): string
{
$map = $this->getAppVariableNames();
if (empty($map)) {
return $string;
}

$variables = [];
$replacements = [];
foreach ($map as $key => $value) {
$variables[] = '/\{\$' . $key . '\}/';
$replacements[] = '{$' . $value . '}';
}

return preg_replace($variables, $replacements, $string);
}

}

0 comments on commit a8bfeae

Please sign in to comment.