From f18769e282fe4cd321c90e30fd0df6c21d1f0d8e Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Mon, 9 Nov 2020 21:47:56 -0500 Subject: [PATCH] Check that mail templates/layouts exist before extracting view content (#5322) Co-authored-by: Luke Towers Co-authored-by: Ben Thomson --- modules/system/models/MailLayout.php | 49 +++++++++++++++++++++++- modules/system/models/MailPartial.php | 36 +++++++++++++++++- modules/system/models/MailTemplate.php | 52 ++++++++++++++++++++++++-- 3 files changed, 131 insertions(+), 6 deletions(-) diff --git a/modules/system/models/MailLayout.php b/modules/system/models/MailLayout.php index 42b410fe2..48018e39d 100644 --- a/modules/system/models/MailLayout.php +++ b/modules/system/models/MailLayout.php @@ -50,6 +50,12 @@ class MailLayout extends Model public static $codeCache; + /** + * Fired before the model is deleted. + * + * @return void + * @throws ApplicationException if the template is locked + */ public function beforeDelete() { if ($this->is_locked) { @@ -57,6 +63,11 @@ class MailLayout extends Model } } + /** + * List MailLayouts codes keyed by ID. + * + * @return array + */ public static function listCodes() { if (self::$codeCache !== null) { @@ -66,11 +77,23 @@ class MailLayout extends Model return self::$codeCache = self::lists('id', 'code'); } + /** + * Return the ID of a MailLayout instance from a defined code. + * + * @param string $code + * @return string + */ public static function getIdFromCode($code) { return array_get(self::listCodes(), $code); } + /** + * Find a MailLayout instance by its code or create a new instance from the view file. + * + * @param string $code + * @return MailLayout + */ public static function findOrMakeLayout($code) { $layout = self::whereCode($code)->first(); @@ -87,6 +110,7 @@ class MailLayout extends Model /** * Loops over each mail layout and ensures the system has a layout, * if the layout does not exist, it will create one. + * * @return void */ public static function createLayouts() @@ -107,6 +131,13 @@ class MailLayout extends Model } } + /** + * Fill model using a view file retrieved by code. + * + * @param string|null $code + * @return void + * @throws ApplicationException if a layout with the defined code is not registered. + */ public function fillFromCode($code = null) { $definitions = MailManager::instance()->listRegisteredLayouts(); @@ -122,6 +153,12 @@ class MailLayout extends Model $this->fillFromView($definition); } + /** + * Fill model using a view file retrieved by path. + * + * @param string $path + * @return void + */ public function fillFromView($path) { $sections = self::getTemplateSections($path); @@ -150,8 +187,18 @@ class MailLayout extends Model $this->content_text = array_get($sections, 'text'); } + /** + * Get section array from a view file retrieved by code. + * + * @param string $code + * @return array|null + */ protected static function getTemplateSections($code) { - return MailParser::parse(FileHelper::get(View::make($code)->getPath())); + if (!View::exists($code)) { + return null; + } + $view = View::make($code); + return MailParser::parse(FileHelper::get($view->getPath())); } } diff --git a/modules/system/models/MailPartial.php b/modules/system/models/MailPartial.php index 5d003fcf0..a26dc345e 100644 --- a/modules/system/models/MailPartial.php +++ b/modules/system/models/MailPartial.php @@ -42,6 +42,11 @@ class MailPartial extends Model 'content_html' => 'required', ]; + /** + * Fired after the model has been fetched. + * + * @return void + */ public function afterFetch() { if (!$this->is_custom) { @@ -49,6 +54,12 @@ class MailPartial extends Model } } + /** + * Find a MailPartial instance by code or create a new instance from a view file. + * + * @param string $code + * @return MailTemplate + */ public static function findOrMakePartial($code) { try { @@ -68,6 +79,7 @@ class MailPartial extends Model /** * Loops over each mail layout and ensures the system has a layout, * if the layout does not exist, it will create one. + * * @return void */ public static function createPartials() @@ -98,6 +110,12 @@ class MailPartial extends Model } } + /** + * Fill model using a view file retrieved by code. + * + * @param string|null $code + * @return void + */ public function fillFromCode($code = null) { $definitions = MailManager::instance()->listRegisteredPartials(); @@ -113,6 +131,12 @@ class MailPartial extends Model $this->fillFromView($definition); } + /** + * Fill model using a view file retrieved by path. + * + * @param string $path + * @return void + */ public function fillFromView($path) { $sections = self::getTemplateSections($path); @@ -122,8 +146,18 @@ class MailPartial extends Model $this->content_text = array_get($sections, 'text'); } + /** + * Get section array from a view file retrieved by code. + * + * @param string $code + * @return array|null + */ protected static function getTemplateSections($code) { - return MailParser::parse(FileHelper::get(View::make($code)->getPath())); + if (!View::exists($code)) { + return null; + } + $view = View::make($code); + return MailParser::parse(FileHelper::get($view->getPath())); } } diff --git a/modules/system/models/MailTemplate.php b/modules/system/models/MailTemplate.php index 9940b271e..4cd637e29 100644 --- a/modules/system/models/MailTemplate.php +++ b/modules/system/models/MailTemplate.php @@ -47,6 +47,7 @@ class MailTemplate extends Model /** * Returns an array of template codes and descriptions. + * * @return array */ public static function listAllTemplates() @@ -60,6 +61,7 @@ class MailTemplate extends Model /** * Returns a list of all mail templates. + * * @return array Returns an array of the MailTemplate objects. */ public static function allTemplates() @@ -68,7 +70,9 @@ class MailTemplate extends Model $codes = array_keys(self::listAllTemplates()); foreach ($codes as $code) { - $result[] = self::findOrMakeTemplate($code); + if (View::exists($code)) { + $result[] = self::findOrMakeTemplate($code); + } } return $result; @@ -76,6 +80,7 @@ class MailTemplate extends Model /** * Syncronise all file templates to the database. + * * @return void */ public static function syncAll() @@ -117,6 +122,11 @@ class MailTemplate extends Model } } + /** + * Fired after the model has been fetched. + * + * @return void + */ public function afterFetch() { if (!$this->is_custom) { @@ -124,31 +134,65 @@ class MailTemplate extends Model } } + /** + * Fill model using provided content. + * + * @param string $content + * @return void + */ public function fillFromContent($content) { $this->fillFromSections(MailParser::parse($content)); } + /** + * Fill model using a view file path. + * + * @param string $path + * @return void + */ public function fillFromView($path) { $this->fillFromSections(self::getTemplateSections($path)); } + /** + * Fill model using provided section array. + * + * @param array $sections + * @return void + */ protected function fillFromSections($sections) { - $this->content_html = $sections['html']; - $this->content_text = $sections['text']; + $this->content_html = array_get($sections, 'html'); + $this->content_text = array_get($sections, 'text'); $this->subject = array_get($sections, 'settings.subject', 'No subject'); $layoutCode = array_get($sections, 'settings.layout', 'default'); $this->layout = MailLayout::findOrMakeLayout($layoutCode); } + /** + * Get section array from a view file retrieved by code. + * + * @param string $code + * @return array|null + */ protected static function getTemplateSections($code) { - return MailParser::parse(FileHelper::get(View::make($code)->getPath())); + if (!View::exists($code)) { + return null; + } + $view = View::make($code); + return MailParser::parse(FileHelper::get($view->getPath())); } + /** + * Find a MailTemplate record by code or create one from a view file. + * + * @param string $code + * @return MailTemplate model + */ public static function findOrMakeTemplate($code) { $template = self::whereCode($code)->first();