This forum has moved to a new location and is in read-only mode. Please visit talk.octobercms.com to access the new location.

g.frenken68086
g.frenken68086

I would like know if it is possible to override a plugin's Mail Templates without touching the plugin.

For example, when a new RainLab.User is invited, it sends an email using the rainlab.user::mail.invite template. Ideally, I would like to have a Mail Template file in my own plugin's views/mail directory that gets used instead.

I am aware I can simply edit Mail Templates in the backend as they are stored in the database, but I have 2 reasons not to do this:

  1. It will create discrepencies in the Mail Templates across multiple environments, I only want to manage them in the filesystem.
  2. I want to be able to use the RainLab.Translate plugin's feature that allows me to have multi-lingual Mail Templates by providing the Mail Template's filename with a language suffix.
g.frenken68086
g.frenken68086

Update: I have found a solution. If seems a little dirty and unsafe but it's good enough for my use case. Perhaps someone can reply a better solution.

/**
 * Event handler to attempt to override another plugin's Mail Templates
 *
 * This will only work if the Mail Template file matches the original file's name,
 * and is located in the same directory as in the original plugin.
 *
 * Example: if the original file is 'vendor/someplugin/views/mail/contact/new_submission.htm',
 * you will have to match this directory structure and filename in your own template file.
 */
\Event::listen('mailer.beforeSend', function ($view, $data, $callback) {
    if ( ! array_key_exists('skipMailTemplateCheck', $data) || ! $data['skipMailTemplateCheck']) {
        // This event handler can only process view codes in string format
        if ( ! is_string($view)) {
            return true;
        }

        $viewParts = explode('::', $view);

        if ( ! str_contains($viewParts[0], 'yournamespace')) {
            // Set 'skipMailTemplateCheck' so the subsequent send attempt doesn't get checked, creating a loop
            $data['skipMailTemplateCheck'] = true;

            // Set the view's namespace to 'yournamespace.yourpluginname'
            $newView = 'yournamespace.yourpluginname::' . $viewParts[1];

            // If the new view code can be resolved, update $view
            if (\View::exists($newView)) {
                $view = $newView;
            }

            // Send the mail with the new or original view
            \Mail::send($view, $data, $callback);

            // Prevent the original Mailer instance from being sent
            return false;
        }
    }

    return true;
});
daftspunky
daftspunky

Good solution! Thanks for sharing it

1-3 of 3

You cannot edit posts or make replies: the forum has moved to talk.octobercms.com.