<?php
/**
* The base page, model, view and controller classes
*
* @package Tina-MVC
* @subpackage Core
* @author Francis Crossen <hide@address.com>
*/
namespace TINA_MVC {
/**
* The page class
*
* Checks the controller request and permissions.
*
* If permissions are not met, and the $tina_mvc_app_settings->login_redirect is in use
* redirects to a custom login page.
*
* Else $tina_mvc_app_settings->no_permission_behaviour is checked to see what way to handle the
* condition.
*
* If permissions are met, locates and includes the controller and instantiates it. The
* $tina_mvc_request is passed to the controller class. The controller
* set the post title and content. The calling code can later retrive these variables.
*
* @package Tina-MVC
* @subpackage Core
*
* @param string $request /tina_mvc-page/controller/method/and/other/data/to/pass
* @param mixed $role_to_view comma separated string or string or array of roles.
* @param mixed $capability_to_view FALSE allows general access, OR comma separated string or string or array of capabilities. Overrides the role check
* @param mixed $called_from 'PAGE_FILTER', 'WIDGET', 'SHORTCODE' or 'CALL_CONTROLLLER_FUNC'
* @param string $custom_folder an overriding location to look for the controller in
* @param string $shortcode_content the content encapsulated by the tina_mvc shortcode (if any)
*
*/
class tina_mvc_page_class {
/**
* Tina MVC does nopt support direct access to class variables. Use setters and getters.
* @var mixed
*/
protected
$allow_http_redirects,
$MODEL, $CONTROLLER,
$view_data,
$called_from,
$tina_mvc_page,
$request, $raw_request,
$find_app_file_error,
$is_404;
/**
* Checks permissions and instantiates the controller. Sets the page title and content.
*
* @param String $raw_request a path /tina_mvc-page/controller/method/and/other/data/to/pass
* @param Boolean $role_to_view FALSE allows all to view; '' must be loogged in to view; array or comma separated list of roles to view
* @param Boolean $capability_to_view as for $role_to_view. Overrides the $role_to_view
* @param String $called_from 'PAGE_FILTER', 'WIDGET', 'SHORTCODE' or 'CALL_CONTROLLLER_FUNC'
* @param Boolean $custom_folder custom location for the controller
* @param Object $shortcode_content
*/
function __construct( $raw_request='', $role_to_view=NULL, $capability_to_view=NULL, $called_from='PAGE_FILTER', $custom_folder=FALSE, $shortcode_content=FALSE ) {
$this->raw_request = $raw_request;
$this->request = str_replace( '-', '_', $raw_request );
$this->request = explode( '/', $this->request );
$this->called_from = $called_from;
/**
* Locate and instantiate a controller. It can override the default permissions so we need it now
*/
$countroller_found = $this->get_instance_of( $custom_folder, $shortcode_content );
$this->CONTROLLER->set_request( $this->request, $this->raw_request );
$this->CONTROLLER->set_called_from( $this->called_from );
if( isset( $this->CONTROLLER->role_to_view ) ) {
$role_to_view = merge_permissions( $role_to_view, $this->CONTROLLER->role_to_view );
}
if( isset( $this->CONTROLLER->capability_to_view ) ) {
$capability_to_view = merge_permissions( $capability_to_view, $this->CONTROLLER->capability_to_view );
}
// pr( $role_to_view ); pr( $capability_to_view );
$view_ok = FALSE; // default
// watch the boolean checks here. Loose type checking for $capability_to_view
if( ! $capability_to_view AND $role_to_view === FALSE ) {
$view_ok = 'View OK for all';
}
elseif( $capability_to_view === FALSE AND $role_to_view == '' AND is_user_logged_in() ) {
$view_ok = 'View OK for all logged in';
}
elseif( ($capability_to_view !== FALSE) AND user_has_capability($capability_to_view) ) {
$view_ok = 'View OK by CAPABILITY';
}
elseif( ($role_to_view !== FALSE) AND user_has_role($role_to_view) ) {
$view_ok = 'View OK by ROLE';
}
elseif( $this->called_from === 'PAGE_FILTER' ) {
/**
* Are we using custom login functionality?
*/
if( ($custom_login = get_tina_mvc_setting('custom_login')) ) {
if( $this->do_login() ) {
/**
* User is successfully authenticated.
*
* We only do a redirect from a Tina MVC page, i.e. not from a widget or a shortcode where
* browser output has already started.
*
* If login returns TRUE we have an authenticated user and need to go through the various
* role and capability checks again.
*/
$r = get_tina_mvc_setting('logon_redirect_target');
$tina_pages = get_tina_mvc_setting('tina_mvc_pages');
if( $r ) {
if( ! array_key_exists( $r, $tina_pages ) ) {
error('Page in $tina_mvc_app_settings->logon_redirect_target is not a Tina MVC page.');
}
wp_safe_redirect( site_url().'?p='.$tina_pages[$r]['page_id'] );
exit();
}
elseif( $r === '' ) {
wp_safe_redirect( site_url().'?p='.$tina_pages[$custom_login]['page_id'] );
exit();
}
else {
wp_redirect( site_url() );
exit();
}
}
}
elseif( get_tina_mvc_setting('no_permission_behaviour') == 'wp_login' ) {
$login_redir = wp_login_url( site_url( $this->raw_request ) );
wp_redirect( $login_redir );
exit();
}
else {
/**
* If do_login() returns FALSE or we are not using the custom login functionality, a user is not
* logged in and a login form is in $this->the_post_content.
*/
$view_ok = FALSE;
$this->the_post_title = $this->CONTROLLER->get_post_title();
$this->the_post_content = $this->CONTROLLER->get_post_content();
}
}
else {
$view_ok = FALSE;
}
// log( $view_ok ); // debugging permissions
// prd( $this->the_post_content );
/**
* Check the $view_ok setting
*
* In cases where the constructor has set the post_title and post_content we don't want them
* accidently displayed if permission checks do not pass.
*/
if( $view_ok ) {
$this->CONTROLLER->dispatch();
$this->the_post_title = $this->CONTROLLER->get_post_title();
$this->the_post_content = $this->CONTROLLER->get_post_content();
}
elseif( $this->called_from === 'PAGE_FILTER' ) {
if( get_tina_mvc_setting('custom_login') ) {
$this->the_post_title = $this->CONTROLLER->get_post_title();
$this->the_post_content = $this->CONTROLLER->get_post_content();
}
else {
if( get_tina_mvc_setting('no_permission_behaviour') == 'redirect' ) {
wp_redirect( site_url() );
exit;
}
else { // 'no_permission'
$this->the_post_title = 'No Permission';
$this->the_post_content = 'Sorry, you do not have permission to view this content.';
}
}
}
else {
$this->the_post_title = '';
$this->the_post_content = '';
}
}
/**
* Include a controller and set up the Tina MVC request
*
* @param Boolean $controller_file Full path and filename of controller to include
* @param String $controller_name the class to instantiate
* @return object Tina MVC controller
*/
private function include_controller( $controller_file=FALSE, $controller_name='' ) {
if( ! class_exists( $_c = $controller_name.'_controller' )) {
include( $controller_file );
}
if( class_exists( $_c ) ) {
$this->CONTROLLER = new $_c( $this->request, $this->called_from );
$this->CONTROLLER->set_request( $this->request, $this->raw_request );
return TRUE;
}
else {
error( "Class '$controller_name' is not defined in '$controller_file'." );
}
}
/**
* An autoloader
*
* @param string $folder
* @param string $shortcode_content
* @uses $this->include_controller()
*
* @return boolean TRUE on success. FALSE only if called from a shortcode. Other failures trigger an error.
*/
private function get_instance_of( $folder='', $shortcode_content ) {
// $this->called_from = PAGE_FILTER,WIDGET,SHORTCODE,CALL_CONTROLLLER
// $this->request
// pr( $this->called_from );
$this->tina_mvc_page = FALSE; // default - used for page_filter requests
if( $this->called_from == 'PAGE_FILTER' ) {
if( ! $page = $this->request[0] ) {
error( "Invalid request" );
}
else {
$this->tina_mvc_page = $page;
if( isset($this->request[1]) ) {
$controller = $this->request[1];
}
else {
$controller = $this->request[1] = 'index';
}
}
}
else {
$controller = $this->request[0];
}
$controller_filename = $controller.'_controller.php';
/**
* Checks the custom folder
*/
if( $folder ) {
if( file_exists( "$folder/$controller_filename" ) ) {
$this->include_controller( "$folder/$controller_filename", $controller );
return TRUE;
}
$err_msg = "<strong>Controller file '$folder/$controller_filename' does not exist.</strong>";
if( $this->called_from == 'SHORTCODE' OR $this->called_from == 'WIDGET' ) {
$this->CONTROLLER = new tina_mvc_controller_class();
$this->CONTROLLER->set_post_content($err_msg);
return FALSE;
}
else {
error($err_msg);
}
}
$search_errors = array(); // default
$controller_file = find_app_file( $controller_filename, $this->tina_mvc_page, $this->called_from, $search_errors );
if( $controller_file !== FALSE ) {
$this->include_controller( $controller_file, $controller );
return TRUE;
}
else {
/**
* If we got here we have failed to find a controller
*/
if( get_tina_mvc_setting('missing_page_controller_action') == 'display_error' ) {
$e = "<strong>Can't find controller for request:</strong>";
$e .= "<small><pre>".print_r( $this->request, 1 )."</pre></small>\r\n";
$e .= "Looked for file '".$controller."_controller.php' in:";
$e .= "<small><pre>";
foreach( $search_errors AS $d ) {
$e .= str_replace( plugin_folder(), '', $d ) . "\r\n";
}
$e .= "</pre></small>\r\n";
if( $this->called_from == 'SHORTCODE' OR $this->called_from == 'WIDGET' ) {
$this->request = array();
$this->CONTROLLER = new tina_mvc_controller_class();
$this->CONTROLLER->set_post_content($e);
return FALSE;
}
else {
error( $e, $suppress_esc=TRUE );
}
}
elseif( get_tina_mvc_setting('missing_page_controller_action') == 'display_404' ) {
$this->request = array();
$this->CONTROLLER = new tina_mvc_controller_class();
$this->CONTROLLER->set_post_content(FALSE);
$this->is_404 = TRUE;
return FALSE;
}
elseif( get_tina_mvc_setting('missing_page_controller_action') == 'redirect' ) {
wp_redirect( site_url() );
exit();
}
else{
error('TODO: Error setting '.get_tina_mvc_setting('missing_page_controller_action').' not implemented');
}
}
// will get here in event of a 404
// I am sooo confident we'll never get here that..
// die('If you can read this my confidence in line '.__LINE__.' of '.__FILE__.' was misplaced. :-|');
}
/**
* Displays and processes a login form
*
* Used if a user is not authorised to view. Forces a login
*
* @return Boolean TRUE if user passed authentication
*/
private function do_login() {
include_helper('form');
$f = new form( 'login_form' );
$f_user_login = $f->add_field( 'user_login', 'text' )->add_validation( array('required'=>NULL) );
$f_password = $f->add_field( 'user_password', 'password' )->add_validation( array('required'=>NULL) );
$f_remember_me = $f->add_field( 'remember', 'checkbox' );
$f_submit = $f->add_field( 'wp_submit', 'submit', $label='Login');
if( $credentials = $f->get_posted_data() ) { // form was submitted successfully
$u = wp_signon( $credentials, false );
if( !is_wp_error($u) ) {
return TRUE; // we are logged in and done ...
}
else {
$f->add_error( 'The username and/or password is incorrect.' );
}
}
// if we got here we are not authenticated - display the form...
// if there is a _do_login view we will use it...
$login_form = $f->render();
$this->CONTROLLER->add_var( 'login_form', $login_form );
$this->CONTROLLER->set_post_title( 'Login to Continue' );
$this->CONTROLLER->set_post_content( $this->CONTROLLER->load_view( 'tina_mvc_do_login' ) );
return FALSE;
}
/**
* Setter
*/
private function set_404() {
$this->is_404 = TRUE;
}
/**
* Getter
* @return boolean
*/
public function is_404() {
return $this->is_404;
}
/**
* Gets the Wordpress Tina MVC page title
*
* @return string
*/
public function get_post_title() {
return $this->the_post_title;
}
/**
* Gets the Wordpress Tina MVC page content
*
* @return string
*/
public function get_post_content() {
return $this->the_post_content;
}
}
/**
* The controller class
*
* Setter and getter for the Wordpress $the_post_title, $the_post_content
* variables. Loads HTML view files (templates), merging them with PHP variables
*
* If you want to access the Tina MVC request from the constructor of your derived
* class, you must call the parent constructor. Otherwise use the dispatcher functionality
* and place your code the class methods.
*
* @package Tina-MVC
* @subpackage Core
* @param array $request extracted from $_GET - /controller/action/some/data
* @return boolean
*/
class tina_mvc_controller_class {
/**
* @var array the Tina MVC request array( 'tina_page', 'controller', 'method', 'data1', 'data2', ... )
*/
protected $request;
/**
* @var string 'tina_page/controller/method/data1/data2'
*/
protected $raw_request;
/**
* @var array the Tina MVC page
*/
protected $tina_mvc_page;
/**
* @var string the controllers output
*/
protected $the_post_title, $the_post_content;
/**
* @var boolean whether to use the dispatcher method after creating an instance
* of the derived class.
* @see $this->dispatcher()
*/
public $use_dispatcher = TRUE;
/**
* @var string if called from a non self-closing shortcode, the content
* @see tina_mvc_shortcode_func()
*/
public $shortcode_content = '';
/**
* @var object View data for passing to a template. Contains 2 objects, one
* for escaped data and one for non escaped data
* @see $this->add_var()
* @see $this->add_var_e()
*/
protected $template_vars;
/**
* @var array overrides the defaults from app_settings.php
*/
public $role_to_view, $capability_to_view;
/**
* Sets the Tina MVC request.
*
* If you are using the dispatcher functionality then you do not need to call this
* constructor from yoru child classes. The Tina MVC request is set by the base controller
* before calling the dispatch() function.
*
* @param array $request the Tina MVC request
* @param string $called_from 'PAGE_FILTER', 'WIDGET', 'SHORTCODE' or 'CALL_CONTROLLLER_FUNC'
*/
function __construct( $request=array(), $called_from='PAGE_FILTER' ) {
$this->called_from = $called_from;
if( $request ) {
$this->request = $request;
if( count( $request ) ) {
$this->tina_mvc_page = $this->request[0];
}
}
}
/**
* An empty function to prevent errors when the dispatcher function attempts to call index().
*
* This function would normally be redefined by your own controller
*/
public function index() {}
/**
* Calls controller functions based on the Tina MVC request (page/controller/function/data1/data2/...)
*
* If there is no function call in the Tina MVC request, $this->index() is called. Otherwise looks
* for a class method based on the function part of the request. This allows you to name your class
* methods according to your actions. e.g. page/controller/my-action will be mapped on to $this->my_action().
* Default action is always $this->index()
*
* The dispatcher is used by default.
*
* Make any methods that you do not want called by the dispatcher method 'private'
* for security and name them with a leading underscore to prevent the dispatcher
* from trying to load them. E.g. '_my_method'
*/
public function dispatch() {
if( ! $this->use_dispatcher ) {
return FALSE;
}
if( $this->called_from == 'PAGE_FILTER' ) {
// pop the first array element from $request - this will be the Tina MVC page
array_shift( $this->request );
}
// next is the controller...
array_shift( $this->request );
if( !$this->request OR ! is_array($this->request) OR ! $this->request[0] ) {
$this->index();
}
else {
$method = $this->request[0];
if( method_exists( $this , $method ) AND $method[0] !== '_' ) {
// check it isn't private
$m = new \ReflectionMethod( $this, $method );
if( $m->isPublic() ) {
$this->$method( $this->request );
}
}
else {
// tina_mvc_error( 'Method '.$method.' doesn\'t exist.' );
$this->index( $this->request );
}
}
}
/**
* Sets the Tina MVC raw_request (handy to have if you need the original uri)
*
* @param string $request
* @param string $raw_request
*/
public function set_request( $request=array(), $raw_request='' ) {
$this->request = $request;
$this->raw_request = $raw_request;
if( count( $request ) ) {
$this->tina_mvc_page = $request[0];
}
}
/**
* Sets the Tina MVC page title from your application
*
* @param string
*/
public function set_post_title($str) {
$this->the_post_title = $str;
}
/**
* Setter
*
* @param string
*/
public function set_called_from( $c='PAGE_FILTER' ) {
$this->called_from = $c;
}
/**
* Sets the Tina MVC page content from your application
*
* @param string
*/
public function set_post_content($str) {
$this->the_post_content = $str;
}
/**
* Gets the Wordpress Tina MVC page title
*
* Used by tina_mvc_controller_class
*
* @return string
*/
public function get_post_title() {
return $this->the_post_title;
}
/**
* Gets the Wordpress Tina MVC page content
*
* Used by tina_mvc_controller_class
*
* @return string
*/
public function get_post_content() {
return $this->the_post_content;
}
/**
* Includes and parses a view file or an email file
*
* @param string $f full path and filename to file
* @param mixed $V the view data
* @param boolean $add_html_comments Add HTML comments at the start and end of the view file
* @return mixed FALSE or the parsed view file
*/
private function parse_view_file( $f, &$V, $add_html_comments=TRUE ) {
if( ! file_exists( $f ) ) {
return FALSE;
}
else {
if( ! defined('TINA_MVC_LOAD_VIEW') ) define('TINA_MVC_LOAD_VIEW',true);
ob_start();
if( $add_html_comments ) echo "<!--// TINA_MVC VIEW FILE START: $f //-->\r\n";
if( ! empty( $V ) ) {
if( ! is_array($V) ) {
$V = get_object_vars($V);
}
extract( $V );
}
include( $f );
if( $add_html_comments ) echo "<!--// TINA_MVC VIEW FILE END: $f //-->\r\n";
return ob_get_clean();
}
}
/**
* Includes/Parses a HTML file and return as a string
*
* Looks for a file in the same folder as the controller named {$view}_view.php and
* includes it. Any variables passed in $V are extracted into the global scope of the
* HTML view file. This allows the use of <code><?php echo $whatever ?></code> and
* <code><?= $somearray[0] ?></code> template constructs.
*
* In fact we can use any <code><?php foreach($array as $element): ?> .. do something .. <?php endforeach; ?></code>
* just like in normal PHP mixed HTML/PHP templating.
* {$view}_view.php is intended to be a HTML file
*
* If $view is FALSE and $V is string, the string data is used as the parsed view file. i.e. without
* requiring a view file.
*
* Alternatively you can assign template data to $this->template_vars using $this->add_var()
* and $this->add_var_e(). If data is in $this->template_vars it will be used in preference
* to data passed to this function.
*
* You should use <code>if( !defined('TINA_MVC_LOAD_VIEW') ) die;</code> or something
* similar to avoid users being able to call the template directly.
*
* @param string $view the name of the view file (without '_view.php')
* @param mixed $V variable (usually array or object) passed to the included file for parsing by the template
* @param string $custom_folder an overriding location to load the view from (relative to the Tina MVC plugin folder)
*
* @return string the parsed view file (usually HTML)
*
* @see $this->view_data
*/
public function load_view($view=false, & $V=NULL, $custom_folder=FALSE) {
if( is_null( $V ) ) {
$V = & $this->view_data;
}
$post_content = '';
if( $view ) {
$view_filename = $view.'_view.php';
}
//custom location?
if( $view AND $custom_folder AND ! ( $post_content = $this->parse_view_file( $custom_folder.'/'.$view_filename, $V ) ) ) {
error( "Can't find custom view file: '$custom_folder/$view_filename'." );
}
if( $view ) {
$search_errors = array();
$view_file = find_app_file( $view_filename, $this->tina_mvc_page, $this->called_from, $search_errors );
}
if( $view_file !== FALSE ) {
$post_content = $this->parse_view_file( $view_file, $V );
}
if( ! $post_content ) {
// if the view data is a string, we'll just output it...
if( ! $view_file AND is_string( $V ) ) {
$post_content = "<!--// TINA_MVC VIEW FILE START: [string data used instead of a file] //-->\r\n";
$post_content .= $V;
$post_content .= "<!--// TINA_MVC VIEW FILE END: [string data used instead of a file] //-->\r\n";
}
else {
// error
$e = "Can't find view file:\r\n";
$e .= "<small><pre>".$view_filename."</pre></small>\r\n";
$e .= "Looked in:\r\n";
$e .= "<small><pre>";
foreach( $search_errors AS $d ) {
$e .= str_replace( plugin_folder(), '', $d ) . "\r\n";
}
$e .= "</pre></small>\r\n";
error( $e, $suppress_esc=TRUE );
}
}
return $post_content;
}
/**
* Add a variable to $this->template_vars
*
* Allows you to drop your template variables into an object for retrieval by
* $this->load_vew()
*
* The key is added as a property of (object) $this->template_vars
*
* @param string $key the object property name to use when adding data
* @param mixed $v variable to add
* @param boolean $esc whether to escape data or not
* @return boolean
* @see $this->template_vars
* @see $this->add_var_e()
* @see $this->load_view()
*/
public function add_var( $key=NULL, $v=NULL , $esc=FALSE ) {
if( is_null($key) ) {
tina_mvc_error( '$key parameter is required.' );
}
if( $esc ) {
$v = esc_html_recursive( $v );
}
$this->view_data["$key"] = $v;
}
/**
* Add an escaped variable to $this->view_data
*
* Any variables added using this will be escaped. Allows you to drop your
* template variables into an object for retrieval by $this->load_vew()
*
* @param string $key the object property name to use when adding data
* @param mixed $v variable to add
* @return boolean
* @see $this->view_Data
* @see $this->add_var()
* @see $this->load_view()
*/
public function add_var_e( $key=NULL, $v=NULL ) {
if( is_null($key) ) {
tina_mvc_error( '$key parameter is required.' );
}
$this->add_var( $key , $v , TRUE );
return TRUE;
}
/**
* Includes a model
*
* The same search order is used as for controllers
*
* @param string $f the full path and filname
* @param string $m the model name
*
* @return mixed the model object or FALSE
*/
private function include_model( $f, $m ) {
include_once( $f );
if( class_exists( $m ) ) {
$model = new $m;
/**
* Duplicates the tina_mvc_model_class constructor() function. Derived models do not
* need to call the parent constructor.
*/
global $wpdb;
$model->DB = & $wpdb;
$model->wpdb = & $wpdb;
return $model;
}
else {
error( "Model '$m' is not defined in file '$f'." );
}
}
/**
* Locates a Tina MVC model file and return an instance of the model class
*
* Looks for a file in the same order as for controllers and view files. Model files are named {$model}_model.php and
* define a class called {$model}
*
* @param string $model the name of the model file (without '_model.php')
* @param string $custom_folder path to load the model from
* @return object an instance of the model class
*/
public function load_model( $model='', $custom_folder=FALSE ) {
if( ! $model ) {
tina_mvc_error(__FILE__.' :: '.__FUNCTION__.' ('.__LINE__.') requires $model argument.');
}
$model_filename = $model.'_model.php';
//custom location?
if( $custom_folder ) {
if( file_exists( ($f="$custom_folder/$model_filename") ) ) {
return $this->include_model( $f, $model );
}
error( "File '$model_filename' does not exist in location '$custom_folder'." );
}
$search_errors = array();
if( $f = find_app_file( $model_filename, $this->tina_mvc_page, $this->called_from, $search_errors ) ) {
return $this->include_model( $f, $model );
}
// we have an error if we get here...
// error
$e = "Can't find model file:\r\n";
$e .= "<small><pre>".$model_filename."</pre></small>\r\n";
$e .= "Looked in:\r\n";
$e .= "<small><pre>";
foreach( $search_errors AS $d ) {
$e .= str_replace( plugin_folder(), '', $d ) . "\r\n";
}
$e .= "</pre></small>\r\n";
error( $e, $suppress_esc=TRUE );
}
/**
* Grabs an email message template and merges it with any variables you pass. Use this for
* any emails you want to send through Tina MVC. Templates are like normal Tina MVC view files except
* they are named *_email.php.
*
* The templates are stored in the user or Tina MVC 'pages', 'shortcodes' and 'widgets' folders
* (just like controllers, views and models).
*
* Variables are extract() ed into the local scope of the message template. $to, $cc, $bcc and $subject will
* also be added to that scope. Beware: this will overwrite variables of the same name passed through
* $message_variables.
*
* You can also send an email without using a template by passing the content of your email as a string to
* $message_variables and leaving $message_template FALSE.
*
* @param mixed $to The recipients address (array or string)
* @param mixed $cc
* @param mixed $bcc
* @param string $subject
* @param string $message_template Template to use (without the '_email.php')
* @param array $message_variables Data to be merged into the message (usually array or object )
* @todo sending attachments
* @return boolean
*/
function mail( $to=FALSE, $cc=FALSE, $bcc=FALSE, $subject, $message_template=FALSE, $message_variables=array() ) {
if( !$to OR ( is_string($to) AND ! is_email($to) ) ) {
return FALSE;
}
$headers = array();
$headers[] = 'From: ' . get_mailer_from_address();
// make sure the to, cc, bcc and subject data is included in the message variables
$message_variables['to'] = $to;
$message_variables['cc'] = $cc;
$message_variables['bcc'] = $bcc;
$message_variables['subject'] = $subject;
if( $message_template ) {
$search_errors = array();
$tpl_file = find_app_file( $message_template.'_email.php', $this->tina_mvc_page, $this->called_from, $search_errors );
if( ! $tpl_file ) {
// if we get here we've an error
$e = "Can't find email file:\r\n";
$e .= "<small><pre>".$tpl_file."</pre></small>\r\n";
$e .= "Looked in:\r\n";
$e .= "<small><pre>";
foreach( $search_errors AS $d ) {
$e .= str_replace( plugin_folder(), '', $d ) . "\r\n";
}
$e .= "</pre></small>\r\n";
error( $e, $suppress_esc=TRUE );
}
else {
$email_body = $this->parse_view_file( $tpl_file, $message_variables, FALSE );
}
}
elseif( is_string( $message_variables ) ) {
$email_body = $message_variables;
}
else {
// $message_variables is not a string and no template file passed to us
error( '$message_variables must be a string if $message_template is FALSE.' );
}
if( $cc ) {
if( is_array( $cc) ) {
foreach( $cc AS $email ) {
$headers[] = 'Cc: '.$email;
}
}
else {
$headers[] = 'Cc: '.$cc;
}
}
if( $bcc ) {
if( is_array( $bcc) ) {
foreach( $bcc AS $email ) {
$headers[] = 'Bcc: '.$email;
}
}
else {
$headers[] = 'Bcc: '.$bcc;
}
}
return wp_mail( $to , $subject, $email_body, $headers, $attachments=FALSE);
}
}
/**
* The Model Class
*
* Derive your models from this class. So far the only thing we do is to globalise the $wpdb variable
* and assign it as a class variable.
*
* @package Tina-MVC
* @subpackage Core
*/
class tina_mvc_model_class {
/**
* The $wpdb object. It is public in case we want to run arbitrary SQL
*
* @var object $DB A reference to $wpdb object
*/
public $DB;
/**
* The $wpdb object. It is public in case we want to run arbitrary SQL
*
* @var object $wpdb A reference to $wpdb object
*/
public $wpdb;
/**
* Constructor
*
* The load_model() function will assign these variables in case you forget to call the parent
* constructor from your derived model class.
*/
public function __construct() {
global $wpdb;
$this->DB = & $wpdb;
$this->wpdb = & $wpdb;
}
}
}