[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
v1
/
lib
/
pkp
/
classes
/
emailTemplate
/
[
Home
]
File: DAO.php
<?php /** * @file classes/emailTemplate/DAO.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2000-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class DAO * * @brief Read and write email templates to the database. */ namespace PKP\emailTemplate; use APP\core\Application; use APP\core\Services; use APP\facades\Repo; use Exception; use Illuminate\Support\Facades\DB; use Illuminate\Support\LazyCollection; use PKP\core\EntityDAO; use PKP\core\PKPApplication; use PKP\db\DAORegistry; use PKP\db\XMLDAO; use PKP\facades\Locale; use PKP\site\Site; use PKP\site\SiteDAO; use Stringy\Stringy; /** * @template T of EmailTemplate * @extends EntityDAO<T> */ class DAO extends EntityDAO { /** @copydoc EntityDAO::$schema */ public $schema = \PKP\services\PKPSchemaService::SCHEMA_EMAIL_TEMPLATE; /** @copydoc EntityDAO::$table */ public $table = 'email_templates'; /** @copydoc EntityDAO::$settingsTable */ public $settingsTable = 'email_templates_settings'; public $defaultTable = 'email_templates_default_data'; /** @copydoc EntityDAO::$primaryKeyColumn */ public $primaryKeyColumn = 'email_id'; /** @copydoc EntityDAO::$primaryTableColumns */ public $primaryTableColumns = [ 'id' => 'email_id', 'key' => 'email_key', 'alternateTo' => 'alternate_to', 'contextId' => 'context_id', 'enabled' => 'enabled', ]; /** * Get the parent object ID column name */ public function getParentColumn(): string { return 'context_id'; } /** * Instantiate a new DataObject */ public function newDataObject(): EmailTemplate { return app(EmailTemplate::class); } /** * @copydoc EntityDAO::insert() * * Custom email templates will need to generate a unique key, * but the key will be set when this template is a customization * of a default template. * * @throws Exception * * @return string The email template key */ public function insert(EmailTemplate $object): string { if (!$object->getData('key')) { $object->setData('key', $this->getUniqueKey($object)); } parent::_insert($object); return $object->getData('key'); } /** * @copydoc EntityDAO::update() */ public function update(EmailTemplate $object) { parent::_update($object); } /** * @copydoc EntityDAO::delete() */ public function delete(EmailTemplate $emailTemplate) { parent::_delete($emailTemplate); } /** * Get a collection of Email Templates matching the configured query * @return LazyCollection<int,T> */ public function getMany(Collector $query): LazyCollection { $rows = $query ->getQueryBuilder() ->get(); return LazyCollection::make(function () use ($rows) { foreach ($rows as $row) { yield $this->fromRow($row); } }); } /** * Get a single email template that matches the given key */ public function getByKey(int $contextId, string $key): ?EmailTemplate { $results = Repo::emailTemplate()->getCollector($contextId) ->filterByKeys([$key]) ->getMany(); return $results->isNotEmpty() ? $results->first() : null; } /** * Get the number of announcements matching the configured query */ public function getCount(Collector $query): int { return $query ->getQueryBuilder() ->get() ->count(); } /** * Retrieve template together with data from the email_template_default_data * * @copydoc EntityDAO::fromRow() */ public function fromRow(object $row): EmailTemplate { /** @var EmailTemplate $emailTemplate */ $emailTemplate = parent::fromRow($row); $schema = $this->schemaService->get($this->schema); $contextDao = Application::getContextDAO(); $supportedLocalesJson = $row->context_id === PKPApplication::CONTEXT_SITE ? DB::table('site')->first()->supported_locales : DB::table($contextDao->settingsTableName) ->where($contextDao->primaryKeyColumn, $row->context_id) ->where('setting_name', 'supportedLocales') ->value('setting_value'); $rows = DB::table($this->defaultTable) ->where('email_key', '=', $emailTemplate->getData('key')) ->whereIn('locale', json_decode($supportedLocalesJson, true)) ->get(); $props = ['name', 'subject', 'body']; $rows->each(function ($row) use ($emailTemplate, $schema, $props) { foreach ($props as $prop) { // Don't allow default data to override custom template data if ($emailTemplate->getData($prop, $row->locale)) { continue; } $emailTemplate->setData( $prop, $this->convertFromDB( $row->{$prop}, $schema->properties->{$prop}->type ), $row->locale ); } }); return $emailTemplate; } /** * Delete all email templates for a specific locale. */ public function deleteEmailTemplatesByLocale(string $locale) { DB::table($this->settingsTable)->where('locale', $locale)->delete(); DB::table($this->defaultTable)->where('locale', $locale)->delete(); } /** * Check if a template exists with the given email key for a journal/ * conference/... * * * @return bool */ public function defaultTemplateIsInstalled(string $key) { return DB::table($this->defaultTable)->where('email_key', $key)->exists(); } /** * Get the main email template path and filename. * * TODO add to the Repository */ public function getMainEmailTemplatesFilename() { return 'registry/emailTemplates.xml'; } /** * Install email templates from an XML file. * * @param string $templatesFile Filename to install * @param array $locales List of locales to install data for * @param string|null $emailKey Optional name of single email key to install, * skipping others * @param bool $skipExisting If true, do not install email templates * that already exist in the database * */ public function installEmailTemplates( string $templatesFile, array $locales = [], ?string $emailKey = null, bool $skipExisting = false ): bool { $xmlDao = new XMLDAO(); $data = $xmlDao->parseStruct($templatesFile, ['email']); if (!isset($data['email'])) { return false; } // if locales is empty, it will use the site's installed locales $locales = array_filter(array_map('trim', $locales)); 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 ($skipExisting && $this->defaultTemplateIsInstalled($attrs['key'])) { continue; } // Add localized data $this->installEmailTemplateLocaleData($templatesFile, $locales, $attrs['key']); if (isset($attrs['alternateTo'])) { $contextIds = Services::get('context')->getIds(); foreach ($contextIds as $contextId) { $this->installAlternateEmailTemplates($contextId, $attrs['key']); } } } return true; } /** * Install email template contents from an XML file. * * @param string $templatesFile Filename to install * @param array $locales List of locales to install data for * @param string|null $emailKey Optional name of single email key to install, * skipping others * */ public function installEmailTemplateLocaleData( string $templatesFile, array $locales = [], ?string $emailKey = null ): bool { $xmlDao = new XMLDAO(); $data = $xmlDao->parseStruct($templatesFile, ['email']); if (!isset($data['email'])) { return false; } foreach ($data['email'] as $entry) { $attrs = $entry['attributes']; if ($emailKey && $emailKey != $attrs['key']) { continue; } $name = $attrs['name'] ?? null; $subject = $attrs['subject'] ?? null; $body = $attrs['body'] ?? null; if ($name && $subject && $body) { foreach ($locales as $locale) { DB::table($this->defaultTable) ->where('email_key', $attrs['key']) ->where('locale', $locale) ->delete(); $previous = Locale::getMissingKeyHandler(); Locale::setMissingKeyHandler(fn (string $key): string => ''); $translatedName = $name ? __($name, [], $locale) : $attrs['key']; $translatedSubject = __($subject, [], $locale); $translatedBody = __($body, [], $locale); Locale::setMissingKeyHandler($previous); if ($translatedSubject !== null && $translatedBody !== null) { DB::table($this->defaultTable)->insert([ 'email_key' => $attrs['key'], 'locale' => $locale, 'name' => $translatedName, 'subject' => $this->renameApplicationVariables($translatedSubject), 'body' => $this->renameApplicationVariables($translatedBody), ]); } } } } return true; } /** * Installs the "extra" email templates for a context * * These are default email templates that are not the default email * template for a particular mailable. They are extra templates listed * alongside the default template for this mailable. * * These templates are defined by the presence of the `alternateTo` * attribute in the email templates XML file. For them to appear in the * UI, they must have an entry in the `email_templates` database. */ public function installAlternateEmailTemplates(int $contextId, ?string $emailKey = null): void { $xmlDao = new XMLDAO(); $data = $xmlDao->parseStruct(Repo::emailTemplate()->dao->getMainEmailTemplatesFilename(), ['email']); if (!isset($data['email'])) { throw new Exception('Unable to install email templates.'); } foreach ($data['email'] as $entry) { $attrs = $entry['attributes']; $alternateTo = $attrs['alternateTo'] ?? null; if ($emailKey && $emailKey != $attrs['key']) { continue; } if (!$alternateTo) { continue; } $exists = DB::table($this->defaultTable) ->where('email_key', $alternateTo) ->exists(); if (!$exists) { trigger_error( 'Tried to install email template as an alternate to `' . $alternateTo . '`, but no default template exists with this key. Installing ' . $alternateTo . ' email template first', E_USER_WARNING ); $this->installEmailTemplates(Repo::emailTemplate()->dao->getMainEmailTemplatesFilename(), [], $alternateTo); } DB::table($this->table)->insert([ 'email_key' => $attrs['key'], 'context_id' => $contextId, 'alternate_to' => $attrs['alternateTo'], ]); } } /** * Install email template localized data from an XML file. * * @deprecated Since OJS/OMP 3.2, this data should be supplied via the non-localized email template list and PO files. (pkp/pkp-lib#5461) * * @param string $templateDataFile Filename to install * @param string $locale Locale of template(s) to install * @param string|null $emailKey If specified, the key of the single template * to install (otherwise all are installed) * * @return array|boolean */ public function installEmailTemplateData( string $templateDataFile, string $locale, ?string $emailKey = null ): bool { $xmlDao = new XMLDAO(); $data = $xmlDao->parse($templateDataFile); if (!$data) { return false; } foreach ($data->getChildren() as $emailNode) { $subject = $emailNode->getChildValue('subject'); $body = $emailNode->getChildValue('body'); // Translate variable contents foreach ([&$subject, &$body] as &$var) { $var = preg_replace_callback('{{translate key="([^"]+)"}}', fn ($matches) => __($matches[1], [], $locale), $var); } if ($emailKey && $emailKey != $emailNode->getAttribute('key')) { continue; } DB::table($this->defaultTable) ->where('email_key', $emailNode->getAttribute('key')) ->where('locale', $locale) ->delete(); DB::table($this->defaultTable)->insert([ 'email_key' => $emailNode->getAttribute('key'), 'locale' => $locale, 'subject' => $subject, 'body' => $body, ]); } return true; } /** * @param string $localizedData email template's localized subject or body */ protected function renameApplicationVariables(string $localizedData): string { $map = $this->variablesToRename(); if (empty($map)) { return $localizedData; } $variables = []; $replacements = []; foreach ($map as $key => $value) { $variables[] = '/\{\$' . $key . '\}/'; $replacements[] = '{$' . $value . '}'; } return preg_replace($variables, $replacements, $localizedData); } /** * Override this function on an application level to rename app-specific template variables * * Example: ['contextName' => 'journalName'] */ protected function variablesToRename(): array { return []; } /** * Gets a unique key for an email template * * Use this to generate a unique key before adding a template to the * database. */ protected function getUniqueKey(EmailTemplate $emailTemplate): string { $key = Stringy::create($emailTemplate->getLocalizedData('name')) ->slugify() ->regexReplace('[^a-z0-9\-\_.]', '') ->truncate(30) ->toString(); if (!$key) { $key = uniqid(); } $emailTemplate = $this->getByKey($emailTemplate->getData('contextId'), $key); $i = 0; while ($emailTemplate) { $key = $i ? (substr($key, 0, -1) . $i) : ($key . $i); $emailTemplate = $this->getByKey($emailTemplate->getData('contextId'), $key); $i++; } return $key; } }