/ */ class Workflow_Workflow_Action_SendEmail extends Workflow_ActionAbstract { const DEFAULT_TEMPLATE = 'application/workflow/views/scripts/send-email-template.phtml'; /** * Invoke this action for the given transition and record. * * @param Workflow_Model_Transition $transition transition to invoke this action for. * @param P4Cms_Record $record record to invoke this action for. * @return Workflow_ActionInterface provides fluent interface. */ public function invoke(Workflow_Model_Transition $transition, P4Cms_Record $record) { // collect email options $to = $this->_extract($this->getOption('to')); $toRole = $this->_extract($this->getOption('toRole')); $subject = $this->getOption('subject'); $message = $this->getOption('message'); // list of email recipients $recipients = array(); // get users from 'to' option (if set) if (is_array($to)) { // extract email addresses $emailValidator = new Zend_Validate_EmailAddress; $recipients = array_filter($to, array($emailValidator, 'isValid')); // for other items (representing usernames) get emails from users details $usernames = array_diff($to, $recipients); if (count($usernames)) { foreach (P4Cms_User::fetchAll(array(P4Cms_User::FETCH_BY_NAME => $usernames)) as $user) { $recipients[$user->getFullName()] = $user->getEmail(); } } } // if toRole is specified, add member users to the recipient list if (is_array($toRole)) { foreach (P4Cms_User::fetchByRole($toRole) as $user) { $recipients[$user->getFullName()] = $user->getEmail(); } } // early exit if recipients list is empty if (!count($recipients)) { P4Cms_Log::log("Cannot send email: no recipients specified."); return $this; } // early exit if from- or to-state is invalid try { $fromState = $transition->getFromState(); $toState = $transition->getToState(); } catch (Workflow_Exception $e) { P4Cms_Log::log("Cannot send email: invalid 'from' or 'to' state."); return $this; } // provide default subject if not set by user if (!$subject) { $subject = 'Workflow Transition'; // append record title if possible if ($record->hasField('title')) { $subject .= ': ' . $record->getValue('title'); } } // compose html part of the email body try { $bodyHtml = $this->_renderTemplate($transition, $record); } catch (Exception $exception) { P4Cms_Log::logException("Cannot render email template.", $exception); return $this; } // if custom message is set, prepend it to the body if ($message) { $bodyHtml = '

' . $message . '

' . $bodyHtml; } // compose text part of the email body $htmlToText = new P4Cms_Filter_HtmlToText; $bodyText = $htmlToText->filter($bodyHtml); // send email $this->_sendEmail($recipients, $subject, $bodyText, $bodyHtml); return $this; } /** * Send an email. * * @param string|array $to email recipient. * @param string $subject email subject. * @param string $bodyText email body in the text format. * @param string $bodyHtml email body in the html format. */ protected function _sendEmail($to, $subject, $bodyText, $bodyHtml) { $mail = new Zend_Mail(); $mail->addTo($to) ->setSubject($subject); // set email body if ($bodyText) { $mail->setBodyText($bodyText); } if ($bodyHtml) { $mail->setBodyHtml($bodyHtml); } // set active user (if there is any) as sender if (P4Cms_User::hasActive()) { $user = P4Cms_User::fetchActive(); $mail->setFrom($user->getEmail(), $user->getFullName()); } // send the email try { $mail->send(); } catch (Exception $exception) { P4Cms_Log::logException("Error when sending email.", $exception); } } /** * Convert a string or list of strings with separated items into an array of items. * Returns null for empty input. * * @param null|string|array $input string or list of strings to extract values from. * @param string $separator items separator. * @return null|array array with string values extracted from input or null of * no input is given. */ protected function _extract($input, $separator = ',') { // early exit if no input is given if (!$input) { return null; } $input = (array) $input; $output = array(); foreach ($input as $value) { // convert separated list of values into an array $values = explode($separator, $value); $values = array_map('trim', $values); // add values into output list $output = array_merge($output, $values); } return $output; } /** * Return rendered template. * * @param Workflow_Model_Transition $transition transition to invoke this action for. * @param P4Cms_Record $record record to invoke this action for. * @return string rendered template. */ protected function _renderTemplate(Workflow_Model_Transition $transition, P4Cms_Record $record) { // assemble list with template candidates; first one that can be rendered // by the view script will be returned $candidates = (array) $this->getOption('template'); $candidates[] = static::DEFAULT_TEMPLATE; // we'll render template by the view cloned from MVC instance $view = clone Zend_Layout::getMvcInstance()->getView(); // loop through template candidates and render first one that view // script can find in the script paths foreach ($candidates as $template) { // if template contains path, add path to the view script paths $templateDir = dirname($template); $name = basename($template); if (strlen($templateDir) && $templateDir !== '.') { $path = BASE_PATH . '/' . $templateDir; if (is_dir($path) && is_readable($path . '/' . $name)) { $view->addScriptPath($path); } } // return rendered template if view script can find it if ($view->getScriptPath(basename($name))) { $view->transition = $transition; $view->record = $record; $view->action = $this; return $view->render($name); } } throw new Workflow_Exception("Cannot render template."); } }