375 lines
9.9 KiB
PHP
375 lines
9.9 KiB
PHP
<?php defined('SYSPATH') or die('No direct access allowed.');
|
|
|
|
/**
|
|
* This class provides email template handling in the same manor as views.
|
|
*
|
|
* @package lnApp
|
|
* @category Helpers
|
|
* @author Deon George
|
|
* @copyright (c) 2014 Deon George
|
|
* @license http://dev.leenooks.net/license.html
|
|
*/
|
|
abstract class lnApp_Email extends Kohana_Email {
|
|
// Array of global variables
|
|
protected static $_global_data = array();
|
|
|
|
// View filename
|
|
protected $_file = array();
|
|
|
|
// Array of local variables
|
|
protected $_data = array();
|
|
|
|
// Email Details
|
|
protected $_email = array();
|
|
|
|
// Our email subject key
|
|
private $_key;
|
|
|
|
private $_mime = array(
|
|
'txt'=>'text/plain',
|
|
'htm'=>'text/html',
|
|
);
|
|
|
|
/**
|
|
* Sets the initial view filename and local data. Views should almost
|
|
* always only be created using [Email::factory].
|
|
*
|
|
* $email = new Email($file);
|
|
*
|
|
* @param string $file view filename
|
|
* @param array $data array of values
|
|
* @return void
|
|
* @uses Email::set_filename
|
|
*/
|
|
public function __construct($file=NULL,array $data=NULL) {
|
|
$this->_key = $file;
|
|
|
|
if ($file !== NULL)
|
|
$this->set_filename($file);
|
|
|
|
// Add the values to the current data
|
|
if ($data !== NULL)
|
|
$this->_data = $data + $this->_data;
|
|
}
|
|
|
|
/**
|
|
* Magic method, searches for the given variable and returns its value.
|
|
* Local variables will be returned before global variables.
|
|
*
|
|
* $value = $email->foo;
|
|
*
|
|
* [!!] If the variable has not yet been set, an exception will be thrown.
|
|
*
|
|
* @param string $key variable name
|
|
* @return mixed
|
|
* @throws Kohana_Exception
|
|
*/
|
|
public function & __get($key) {
|
|
if (array_key_exists($key,$this->_data))
|
|
return $this->_data[$key];
|
|
|
|
elseif (array_key_exists($key,$this->_email))
|
|
return $this->_email[$key];
|
|
|
|
elseif (array_key_exists($key,Email::$_global_data))
|
|
return Email::$_global_data[$key];
|
|
|
|
else
|
|
throw new Kohana_Exception('View variable is not set: :var',array(':var'=>$key));
|
|
}
|
|
|
|
/**
|
|
* Magic method, determines if a variable is set.
|
|
*
|
|
* isset($email->foo);
|
|
*
|
|
* [!!] `NULL` variables are not considered to be set by [isset](http://php.net/isset).
|
|
*
|
|
* @param string $key variable name
|
|
* @return boolean
|
|
*/
|
|
public function __isset($key) {
|
|
return (isset($this->_data[$key]) OR isset($this->_email[$key]) OR isset(Email::$_global_data[$key]));
|
|
}
|
|
|
|
/**
|
|
* Magic method, calls [Email::set] with the same parameters.
|
|
*
|
|
* $email->foo = 'something';
|
|
*
|
|
* @param string $key variable name
|
|
* @param mixed $value value
|
|
* @return void
|
|
*/
|
|
public function __set($key,$value) {
|
|
switch ($key) {
|
|
case 'from':
|
|
case 'bcc':
|
|
case 'to':
|
|
if (! is_array($value) OR ! array_intersect(array('email','account'),array_keys($value)))
|
|
throw new Email_Exception('Values for to should be an array of either "mail" or "account", however :value was given',
|
|
array(':value'=>serialize($value)));
|
|
|
|
case 'subject':
|
|
$this->_email[$key] = $value;
|
|
break;
|
|
|
|
default:
|
|
$this->set($key,$value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Magic method, returns the output of [Email::render].
|
|
*
|
|
* @return string
|
|
* @uses Email::render
|
|
*/
|
|
public function __toString() {
|
|
$e = Email::connect();
|
|
|
|
try {
|
|
return (string)$this->render();
|
|
|
|
} catch (Exception $e) {
|
|
/**
|
|
* Display the exception message.
|
|
*
|
|
* We use this method here because it's impossible to throw an
|
|
* exception from __toString().
|
|
*/
|
|
$error_response = Kohana_Exception::_handler($e);
|
|
|
|
return $error_response->body();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Magic method, unsets a given variable.
|
|
*
|
|
* unset($email->foo);
|
|
*
|
|
* @param string $key variable name
|
|
* @return void
|
|
*/
|
|
public function __unset($key) {
|
|
unset($this->_data[$key],$this->_email[$key],Email::$_global_data[$key]);
|
|
}
|
|
|
|
/**
|
|
* Assigns a value by reference. The benefit of binding is that values can
|
|
* be altered without re-setting them. It is also possible to bind variables
|
|
* before they have values. Assigned values will be available as a
|
|
* variable within the view file:
|
|
*
|
|
* // This reference can be accessed as $ref within the view
|
|
* $email->bind('ref', $bar);
|
|
*
|
|
* @param string $key variable name
|
|
* @param mixed $value referenced variable
|
|
* @return $this
|
|
*/
|
|
public function bind($key,&$value) {
|
|
$this->_data[$key] =& $value;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Assigns a global variable by reference, similar to [Email::bind], except
|
|
* that the variable will be accessible to all views.
|
|
*
|
|
* Email::bind_global($key,$value);
|
|
*
|
|
* @param string $key variable name
|
|
* @param mixed $value referenced variable
|
|
* @return void
|
|
*/
|
|
public static function bind_global($key,&$value) {
|
|
Email::$_global_data[$key] =& $value;
|
|
}
|
|
|
|
/**
|
|
* Captures the output that is generated when a view is included.
|
|
* The view data will be extracted to make local variables. This method
|
|
* is static to prevent object scope resolution.
|
|
*
|
|
* $output = Email::capture($file,$data);
|
|
*
|
|
* @param string $kohana_view_filename filename
|
|
* @param array $kohana_view_data variables
|
|
* @return string
|
|
*/
|
|
protected static function capture($kohana_view_filename,array $kohana_view_data) {
|
|
return Email::complete(file_get_contents($kohana_view_filename),Arr::merge(Email::$_global_data,$kohana_view_data));
|
|
}
|
|
|
|
/**
|
|
* Exchange the variables for values
|
|
*/
|
|
private static function complete($output,$data) {
|
|
foreach (Email::variables($output) as $v)
|
|
$output = str_replace('$'.$v.'$',$data[$v],$output);
|
|
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Deliver the email
|
|
*/
|
|
public function deliver(array $admin=array()) {
|
|
// @todo - Setup queue mode
|
|
return Email::connect()->send($this->render(NULL,$admin));
|
|
}
|
|
|
|
/**
|
|
* Get email details
|
|
*/
|
|
private function email($key) {
|
|
if (is_array($this->_email[$key]) AND isset($this->_email[$key]['email']))
|
|
return $this->_email[$key]['email'];
|
|
else
|
|
return (is_array($this->_email[$key]) AND isset($this->_email[$key]['account'])) ? $this->_email[$key]['account'] : $this->_email[$key];
|
|
}
|
|
|
|
/**
|
|
* Returns a new Email object. If you do not define the "file" parameter,
|
|
* you must call [Email::set_filename].
|
|
*
|
|
* $email = Email::factory($file);
|
|
*
|
|
* @param string $file email filename
|
|
* @param array $data array of values
|
|
* @return Email
|
|
*/
|
|
public static function factory($file=NULL,array $data=NULL) {
|
|
return new Email($file,$data);
|
|
}
|
|
|
|
/**
|
|
* Renders the view object to a string. Global and local data are merged
|
|
* and extracted to create local variables within the view file.
|
|
*
|
|
* $output = $email->render();
|
|
*
|
|
* [!!] Global variables with the same key name as local variables will be
|
|
* overwritten by the local variable.
|
|
*
|
|
* @param string $file view filename
|
|
* @return string
|
|
* @throws Email_Exception
|
|
* @uses Email::capture
|
|
*/
|
|
public function render($file=NULL,array $admin=array()) {
|
|
if ($file !== NULL)
|
|
$this->set_filename($file);
|
|
|
|
if (empty($this->_file))
|
|
throw new Email_Exception('You must set the file to use within your email before rendering');
|
|
|
|
if ($x=array_diff(array('to','from','subject'),array_keys($this->_email)))
|
|
throw new Email_Exception('You are missing :missing from the Email',array(':missing'=>join('|',$x)));
|
|
|
|
$sm = Swift_Message::newInstance()
|
|
->setFrom($this->email('from'))
|
|
->setSubject($this->email('subject'));
|
|
|
|
foreach ($this->_file as $file) {
|
|
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
|
$sm->addPart(Email::capture($file,$this->_data),array_key_exists($ext,$this->_mime) ? $this->_mime[$ext] : File::mime($file));
|
|
}
|
|
|
|
// Our list of BCC recipients
|
|
if (Kohana::$config->load('debug')->email_bcc_admin AND $x=Arr::merge($this->email('bcc'),Kohana::$config->load('debug')->email_bcc_admin))
|
|
$sm->setBcc($x);
|
|
|
|
$sm->setTo(($admin OR ($admin = Config::testmail($this->_key))) ? $admin : $this->email('to'));
|
|
|
|
return $sm;
|
|
}
|
|
|
|
/**
|
|
* Assigns a variable by name. Assigned values will be available as a
|
|
* variable within the view file:
|
|
*
|
|
* // This value can be accessed as $foo within the view
|
|
* $email->set('foo','my value');
|
|
*
|
|
* You can also use an array to set several values at once:
|
|
*
|
|
* // Create the values $food and $beverage in the view
|
|
* $email->set(array('food' => 'bread', 'beverage' => 'water'));
|
|
*
|
|
* @param string $key variable name or an array of variables
|
|
* @param mixed $value value
|
|
* @return $this
|
|
*/
|
|
public function set($key,$value=NULL) {
|
|
if (is_array($key))
|
|
foreach ($key as $name => $value)
|
|
$this->_data[$name] = $value;
|
|
|
|
else
|
|
$this->_data[$key] = $value;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Sets the view filename.
|
|
*
|
|
* $email->set_filename($file);
|
|
*
|
|
* @param string $file view filename
|
|
* @return Email
|
|
* @throws Email_Exception
|
|
*/
|
|
public function set_filename($file) {
|
|
foreach (array_keys($this->_mime) as $ext)
|
|
if ($path=Kohana::find_file('email',$file,$ext))
|
|
// Store the file path locally
|
|
array_push($this->_file,$path);
|
|
|
|
if (! $this->_file)
|
|
throw new Email_Exception('The requested email :file could not be found',array(':file'=>$file));
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Sets a global variable, similar to [Email::set], except that the
|
|
* variable will be accessible to all views.
|
|
*
|
|
* Email::set_global($name, $value);
|
|
*
|
|
* @param string $key variable name or an array of variables
|
|
* @param mixed $value value
|
|
* @return void
|
|
*/
|
|
public static function set_global($key,$value=NULL) {
|
|
if (is_array($key))
|
|
foreach ($key as $key2 => $value)
|
|
Email::$_global_data[$key2] = $value;
|
|
|
|
else
|
|
Email::$_global_data[$key] = $value;
|
|
}
|
|
|
|
/**
|
|
* Extract the variables in the text
|
|
*/
|
|
public static function variables($output) {
|
|
$results = array();
|
|
$matches = array();
|
|
|
|
preg_match_all('/\$([A-Z0-9_]+)\$/U',$output,$matches,PREG_OFFSET_CAPTURE);
|
|
|
|
foreach ($matches[1] as $k => $v)
|
|
if (! in_array($v[0],$results))
|
|
array_push($results,$v[0]);
|
|
|
|
return $results;
|
|
}
|
|
}
|
|
?>
|