I have a question regarding loops within an email template. My current email library gets passed an array of data and a template(.html) to search and replace. This works fine if I just need to replace any element wrapped in a square bracket [variable] . My library however can not deal with arrays of data(looping) and I need a more elegant solution than the ugly approach below
Cheers.
Email Library
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
require_once('phpmailer/phpmailer.php');
class Mailer{
protected static $mailer;
protected static $CI;
public function __construct()
{
self::$mailer = new PHPMailer();
self::$CI =& get_instance();
self::$CI->load->helper('file');
}
/**
*
* #param type $data
* #param type $template
* #return type
*/
public static function prepIt($data, $template)
{
$callback = function ($matches) use ($data){
return ( isset($data[$matches[1]]) )
? $data[$matches[1]]
: $matches[0];
};
return preg_replace_callback(
'/\[(.*?)\]/',
$callback,
read_file(EMAIL_TEMPLATES . $template));
}
/**
*
* #param type $data
* #param type $template
* #param type $to
* #param type $subject
* #param type $prep
* #return type
*/
public static function sendIt($data, $template='', $to, $subject, $prep=false)
{
self::$mailer->CharSet = 'utf-8';
if(self::$CI->config->item('email_smtp') === TRUE){
self::$mailer->SMTPSecure = "ssl";
self::$mailer->Host= self::$CI->config->item('email_host');
self::$mailer->Port= self::$CI->config->item('email_port');
self::$mailer->Username = self::$CI->config->item('email_user');
self::$mailer->Password = self::$CI->config->item('email_passw');
self::$mailer->SMTPKeepAlive = true;
self::$mailer->Mailer = "smtp";
self::$mailer->IsSMTP();
self::$mailer->SMTPAuth = true;
self::$mailer->SMTPDebug = 0;
}
if($prep)
{
self::$mailer->Body = self::prepIt($data, $template);
}
else
{
self::$mailer->Body = $data;
}
self::$mailer->IsHTML(true);
self::$mailer->Subject = $subject;
self::$mailer->AddAddress($to);
self::$mailer->FromName = self::$CI->config->item('email_from');
self::$mailer->From = self::$CI->config->item('email_primary');
try{
if(self::$mailer->Send()){
return true;
}else{
throw new phpmailerException(self::$mailer->ErrorInfo);
}
}catch(phpmailerException $e){
log_message('error', $e->getMessage());
}
}
return false;
}
Ugly Approach for non-defined templates
Note: sorry about poor formating here...
Instead of using a pre-made template, I have to pass a template on the fly so I can run a foreach loop with the data
if ($order->update_attributes($update_order)) {
$output ='<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type"content="text/html; charset=utf-8"/><title>Reciept</title><style type="text/css">#outlook a{padding:0;}
body{width:100%!important;}.ReadMsgBody{width:100%;}.ExternalClass{width:100%;}emails at full width*/body{-webkit-text-size-adjust:none;-ms-text-size-adjust:none;}
body{margin:0;padding:0;font:normal 14px tahoma,sans-serif;color:#515151;line-height:1.6em;}
img{height:auto;line-height:100%;outline:none;text-decoration:none;}
a img{border:none;}#backgroundTable{margin:0;padding:0;width:100%!important;}
p{margin-bottom:18px;line-height:1.6;color:#767676;}
h1,h2,h3,h4,h5,h6{color:black!important;line-height:100%!important;}
h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:blue!important;}
h1 a:active,h2 a:active,h3 a:active,h4 a:active,h5 a:active,h6 a:active{color:red!important;}
h1 a:visited,h2 a:visited,h3 a:visited,h4 a:visited,h5 a:visited,h6 a:visited{color:purple!important;}
table td{border-collapse:collapse;}
table th{text-align:left;padding:25px;}.yshortcuts,.yshortcuts a,.yshortcuts a:link,.yshortcuts a:visited,.yshortcuts a:hover,.yshortcuts a span{color:black;text-decoration:none!important;border-bottom:none!important;background:none!important;}
table#product{border-spacing:0;width:100%;}
table#product th{padding:8px;}
table#product td{padding:8px;border-bottom:1px solid#b1b1b1;}</style></head><body><table width="100%" style="background:#e3e3e3;text-align:center;padding:10px;width:100%;"cellpadding="0"cellspacing="0"border="0"id="backgroundTable"><tr><td><table cellpadding="0"cellspacing="0"border="0"width="650"style="text-align:left;padding:8px;background:#ffffff;border:1px solid #b1b1b1;"><thead><tr><th style="text-align:left;font-size:30px;padding:0;">Philip Kavanagh</th><th style="text-align:right;"><img src="http://localhost/crack_ie/assets/front/img/logo.png"alt=""/></th></tr></thead><tbody><tr><td colspan="2"><h2>Reciept</h2><p>Thank you for your recent purchase(s)from the store.<br>The Order has been proccessed by paypal successfully!</p></td></tr><tr><td colspan="2"><h3>Purchase Information</h3><p>Below you will find links to your digital downloads</p></td></tr><tr><td colspan="2"><table class="product"id="product"><thead><tr><td> </td><td>Title</td><td>Price</td><td>Download</td></tr></thead><tbody>';
foreach ($email_data as $out) {
$output .= '
<tr><td><img src="'.site_url(MEDIA . 'products/' . $out['img']).'" alt=""/></td><td>'.$out['title'].'</td><td>€'.$out['price'].'</td><td>Download</td></tr>
';
}
$output .= '
</tbody></table></td></tr><tr><td style="width:70%;"> </td><td style="width:30%;text-align:right;"><table style="text-align:right;border-spacing:0;"><tbody><tr><td style="width:100%;padding:5px;">Order#</td><td style="margin-left:30px;"><strong>7782tgh5</strong></td></tr><tr><td style="width:100%;padding:5px;">Items</td><td style="margin-left:30px;">'.$email_additional['items'].'</td></tr><tr><td>Tax</td><td>€0.00</td></tr><tr style="background:#d53015;color:#fafafa;width:100%;"><td>Total Amount</td><td style="font-size: 30px; padding: 8px;">€'.$email_additional['total'].'</td></tr></tbody></table></td></tr></tbody></table></td></tr></table></body></html>
';
if (Mailer::sendIt($output, '', $user->email, 'Purchase Confirmation: #' . $order->order_sku . '', false)) {
return true;
}
Edit: Answer Thanks to landons,
if ($order->update_attributes($update_order)) {
$output = $this->load->view('orders/email', array(
'data' => $somedata
), true);
if (Mailer::sendIt($output, '', $user->email, 'Purchase Confirmation: #' . $order->order_sku . '', false)) {
return true;
}
}
Have you considered simply passing data to a view (and returning the content, rather than displaying it)?
Related
Can someone help/tell me how to get yclas phpmail to BBC to a mailadres and ad a REPLY TO? its a marketplace script open source.
Thanks for your input, after 3 days i'm getting no results, i'm not a expert.
The phpmail file is:
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Simple email class
*
* #package OC
* #category Core
* #author Chema <chema#open-classifieds.com>, Slobodan <slobodan#open-classifieds.com>
* #copyright (c) 2009-2013 Open Classifieds Team
* #license GPL v3
*/
class Email {
/**
* sends an email using our configs
* #param string/array $to array(array('name'=>'chema','email'=>'chema#'),)
* #param [type] $to_name [description]
* #param [type] $subject [description]
* #param [type] $body [description]
* #param [type] $reply [description]
* #param [type] $replyName [description]
* #param [type] $file [description]
* #return boolean
*/
public static function send($to,$to_name='',$subject,$body,$reply,$replyName,$file = NULL,$content = NULL)
{
$result = FALSE;
//multiple to but theres none...
if (is_array($to) AND count($to)==0)
return FALSE;
$body = Text::nl2br($body);
//get the unsubscribe link
$email_encoded = NULL;
//is sent to a single user get hash to auto unsubscribe
if (!is_array($to) OR count($to)==1)
{
//from newsletter sent
if (isset($to[0]['email']))
$email_encoded = $to[0]['email'];
else
$email_encoded = $to;
//encodig the email for extra security
$encrypt = new Encrypt(Core::config('auth.hash_key'), MCRYPT_MODE_NOFB, MCRYPT_RIJNDAEL_128);
$email_encoded = Base64::fix_to_url($encrypt->encode($email_encoded));
}
$unsubscribe_link = Route::url('oc-panel',array('controller'=>'auth','action'=>'unsubscribe','id'=>$email_encoded));
//get the template from the html email boilerplate
$body_original = $body;
$body = View::factory('email',array('title'=>$subject,'content'=>$body,'unsubscribe_link'=>$unsubscribe_link))->render();
switch (core::config('email.service')) {
case 'elasticemail':
$result = ElasticEmail::send($to,$to_name, $subject, $body, $reply, $replyName);
break;
case 'mailgun':
//todo
break;
case 'pepipost':
//todo
break;
case 'smtp':
case 'mail':
default:
$result = self::phpmailer($to,$to_name,$subject,$body,$reply,$replyName,$file);
break;
}
// notify user (pusher)
if (Core::config('general.pusher_notifications')){
if (is_array($to)){
foreach ($to as $user_email) {
Model_User::pusher($user_email['email'], Text::limit_chars(Text::removebbcode($body), 80, NULL, TRUE),$content);
}
} else
Model_User::pusher($to, Text::limit_chars(Text::removebbcode($body), 80, NULL, TRUE),$content);
}
return $result;
}
/**
* sends an email using content from model_content
* #param string $to
* #param string $to_name
* #param string $from
* #param string $from_name
* #param string $content seotitle from Model_Content
* #param array $replace key value to replace at subject and body
* #param array $file file to attach to email
* #return boolean s
*/
public static function content($to, $to_name='', $from = NULL, $from_name =NULL, $content, $replace, $file=NULL)
{
$email = Model_Content::get_by_title($content,'email');
//content found
if ($email->loaded())
{
if ($replace===NULL)
$replace = array();
if ($from === NULL)
$from = $email->from_email;
if ($from_name === NULL )
$from_name = core::config('general.site_name');
if (isset($file) AND self::is_valid_file($file))
$file_upload = $file;
else
$file_upload = NULL;
//adding extra replaces
$replace+= array('[SITE.NAME]' => core::config('general.site_name'),
'[SITE.URL]' => core::config('general.base_url'),
'[USER.NAME]' => $to_name);
if(!is_array($to))
$replace += array('[USER.EMAIL]'=>$to);
//adding anchor tags to any [URL.* match
foreach ($replace as $key => $value)
{
if(strpos($key, '[URL.')===0 OR $key == '[SITE.URL]' AND $value!='')
$replace[$key] = ''.parse_url($value, PHP_URL_HOST).'';
}
$subject = str_replace(array_keys($replace), array_values($replace), $email->title);
$body = str_replace(array_keys($replace), array_values($replace), $email->description);
return Email::send($to,$to_name,$subject,$body,$from,$from_name, $file_upload,$content);
}
else
return FALSE;
}
/**
* returns true if file is of valid type.
* Its used to check file sent to user from advert usercontact
* #param array file
* #return BOOL
*/
public static function is_valid_file($file)
{
//catch file
$file = $_FILES['file'];
//validate file
if( $file !== NULL)
{
if (
! Upload::valid($file) OR
! Upload::not_empty($file) OR
! Upload::type($file, array('jpg', 'jpeg', 'png', 'pdf','doc','docx')) OR
! Upload::size($file,'3M'))
{
return FALSE;
}
return TRUE;
}
}
/**
* returns an array of administrators and moderators
* #return array
*/
public static function get_notification_emails()
{
$arr = array();
$users = new Model_User();
$users = $users->where('id_role','in',array(Model_Role::ROLE_ADMIN,Model_Role::ROLE_MODERATOR))
->where('status','=',Model_User::STATUS_ACTIVE)
->where('subscriber','=',1)
->cached()->find_all();
foreach ($users as $user)
{
$arr[] = array('name'=>$user->name,'email'=>$user->email);
}
return $arr;
}
/**
* returns the spam score of a raw email using api from postmarkapp
* #param string $raw_email entire RAW email with headers etc....
* #return numeric/false spam score or FALSE is something went wrong....
*/
public static function get_spam_score($raw_email)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, 'http://spamcheck.postmarkapp.com/filter');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array('email' => $raw_email,'options'=>'short')));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
$response = curl_exec($ch);
//something went wrong with the request
if(empty($response) || curl_error($ch) || curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 200){
curl_close($ch);
return FALSE;
}
curl_close($ch);
$score = json_decode($response);
if ($score->success == TRUE AND is_numeric($score->score))
return $score->score;
else
return FALSE;
}
public static function phpmailer($to,$to_name='',$subject,$body,$reply,$replyName,$file = NULL)
{
require_once Kohana::find_file('vendor', 'php-mailer/phpmailer','php');
$mail= new PHPMailer();
$mail->CharSet = Kohana::$charset;
if(core::config('email.service') == 'smtp')
{
require_once Kohana::find_file('vendor', 'php-mailer/smtp','php');
$mail->IsSMTP();
$mail->Timeout = 5;
//SMTP HOST config
if (core::config('email.smtp_host')!="")
$mail->Host = core::config('email.smtp_host'); // sets custom SMTP server
//SMTP PORT config
if (core::config('email.smtp_port')!="")
$mail->Port = core::config('email.smtp_port'); // set a custom SMTP port
//SMTP AUTH config
if (core::config('email.smtp_auth') == TRUE)
{
$mail->SMTPAuth = TRUE; // enable SMTP authentication
$mail->Username = core::config('email.smtp_user'); // SMTP username
$mail->Password = core::config('email.smtp_pass'); // SMTP password
}
// sets the prefix to the server
$mail->SMTPSecure = core::config('email.smtp_secure');
}
$mail->From = core::config('email.notify_email');
$mail->FromName = core::config('email.notify_name');
$mail->Subject = $subject;
$mail->MsgHTML($body);
if($file !== NULL)
$mail->AddAttachment($file['tmp_name'],$file['name']);
$mail->AddReplyTo($reply,$replyName);//they answer here
if (is_array($to))
{
foreach ($to as $contact)
$mail->AddBCC($contact['email'],$contact['name']);
}
else
$mail->AddAddress($to,$to_name);
$mail->IsHTML(TRUE); // send as HTML
//to multiple destinataries, check spam score
if (is_array($to))
{
$mail->preSend();
$spam_score = Email::get_spam_score($mail->getSentMIMEMessage());
if ($spam_score >= 5 OR $spam_score === FALSE)
{
Alert::set(Alert::ALERT,"Please review your email. Got a Spam Score of " . $spam_score);
return $spam_score;
}
}
try {
$result = $mail->Send();
} catch (Exception $e) {
$result = FALSE;
$mail->ErrorInfo = $e->getMessage();
}
if(!$result)
{//to see if we return a message or a value bolean
Alert::set(Alert::ALERT,"Mailer Error: " . $mail->ErrorInfo);
return FALSE;
}
else
return TRUE;
}
} //end email
I'm new so please bear with me.
I am trying to add a BCC recipient to one of codeigniter applications' email.php config file. The original was created by an employee who has since left our business and I am struggling to add a bcc recipient into the code.
I have searched stackoverflow and tried endless variations but I am not having any luck. All I want to do is define one bcc email recipient.
I would really really really appreciate anybody's help :)
Here is a portion of the the current code I think is relevant:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* CodeIgniter
*
* An open source application development framework for PHP 5.1.6 or newer
*
* #package CodeIgniter
* #author ExpressionEngine Dev Team
* #copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
* #license http://codeigniter.com/user_guide/license.html
* #link http://codeigniter.com
* #since Version 1.0
* #filesource
*/
// ------------------------------------------------------------------------
/**
* CodeIgniter Email Class
*
* Permits email to be sent using Mail, Sendmail, or SMTP.
*
* #package CodeIgniter
* #subpackage Libraries
* #category Libraries
* #author ExpressionEngine Dev Team
* #link http://codeigniter.com/user_guide/libraries/email.html
*/
class CI_Email {
var $useragent = "CodeIgniter";
var $mailpath = "/usr/sbin/sendmail"; // Sendmail path
var $protocol = "mail"; // mail/sendmail/smtp
var $smtp_host = ""; // SMTP Server. Example: mail.earthlink.net
var $smtp_user = ""; // SMTP Username
var $smtp_pass = ""; // SMTP Password
var $smtp_port = "25"; // SMTP Port
var $smtp_timeout = 5; // SMTP Timeout in seconds
var $smtp_crypto = ""; // SMTP Encryption. Can be null, tls or ssl.
var $wordwrap = TRUE; // TRUE/FALSE Turns word-wrap on/off
var $wrapchars = "76"; // Number of characters to wrap at.
var $mailtype = "text"; // text/html Defines email formatting
var $charset = "utf-8"; // Default char set: iso-8859-1 or us-ascii
var $multipart = "mixed"; // "mixed" (in the body) or "related" (separate)
var $alt_message = ''; // Alternative message for HTML emails
var $validate = FALSE; // TRUE/FALSE. Enables email validation
var $priority = "3"; // Default priority (1 - 5)
var $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822)
var $crlf = "\n"; // The RFC 2045 compliant CRLF for quoted-printable is "\r\n". Apparently some servers,
// even on the receiving end think they need to muck with CRLFs, so using "\n", while
// distasteful, is the only thing that seems to work for all environments.
var $send_multipart = TRUE; // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override. Set to FALSE for Yahoo.
var $bcc_batch_mode = FALSE; // TRUE/FALSE Turns on/off Bcc batch feature
var $bcc_batch_size = 200; // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch
var $_safe_mode = FALSE;
var $_subject = "";
var $_body = "";
var $_finalbody = "";
var $_alt_boundary = "";
var $_atc_boundary = "";
var $_header_str = "";
var $_smtp_connect = "";
var $_encoding = "8bit";
var $_IP = FALSE;
var $_smtp_auth = FALSE;
var $_replyto_flag = FALSE;
var $_debug_msg = array();
var $_recipients = array();
var $_cc_array = array();
var $_bcc_array = array();
var $_headers = array();
var $_attach_name = array();
var $_attach_type = array();
var $_attach_disp = array();
var $_protocols = array('mail', 'sendmail', 'smtp');
var $_base_charsets = array('us-ascii', 'iso-2022-'); // 7-bit charsets (excluding language suffix)
var $_bit_depths = array('7bit', '8bit');
var $_priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)');
/**
* Constructor - Sets Email Preferences
*
* The constructor can be passed an array of config values
*/
public function __construct($config = array())
{
if (count($config) > 0)
{
$this->initialize($config);
}
else
{
$this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE;
$this->_safe_mode = ((boolean)#ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
}
log_message('debug', "Email Class Initialized");
}
// --------------------------------------------------------------------
/**
* Initialize preferences
*
* #access public
* #param array
* #return void
*/
public function initialize($config = array())
{
foreach ($config as $key => $val)
{
if (isset($this->$key))
{
$method = 'set_'.$key;
if (method_exists($this, $method))
{
$this->$method($val);
}
else
{
$this->$key = $val;
}
}
}
$this->clear();
$this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE;
$this->_safe_mode = ((boolean)#ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
return $this;
}
// --------------------------------------------------------------------
/**
* Initialize the Email Data
*
* #access public
* #return void
*/
public function clear($clear_attachments = FALSE)
{
$this->_subject = "";
$this->_body = "";
$this->_finalbody = "";
$this->_header_str = "";
$this->_replyto_flag = FALSE;
$this->_recipients = array();
$this->_cc_array = array();
$this->_bcc_array = array();
$this->_headers = array();
$this->_debug_msg = array();
$this->_set_header('User-Agent', $this->useragent);
$this->_set_header('Date', $this->_set_date());
if ($clear_attachments !== FALSE)
{
$this->_attach_name = array();
$this->_attach_type = array();
$this->_attach_disp = array();
}
return $this;
}
// --------------------------------------------------------------------
/**
* Set FROM
*
* #access public
* #param string
* #param string
* #return void
*/
public function from($from, $name = '')
{
if (preg_match( '/\<(.*)\>/', $from, $match))
{
$from = $match['1'];
}
if ($this->validate)
{
$this->validate_email($this->_str_to_array($from));
}
// prepare the display name
if ($name != '')
{
// only use Q encoding if there are characters that would require it
if ( ! preg_match('/[\200-\377]/', $name))
{
// add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes
$name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"';
}
else
{
$name = $this->_prep_q_encoding($name, TRUE);
}
}
$this->_set_header('From', $name.' <'.$from.'>');
$this->_set_header('Return-Path', '<'.$from.'>');
return $this;
}
// --------------------------------------------------------------------
/**
* Set Reply-to
*
* #access public
* #param string
* #param string
* #return void
*/
public function reply_to($replyto, $name = '')
{
if (preg_match( '/\<(.*)\>/', $replyto, $match))
{
$replyto = $match['1'];
}
if ($this->validate)
{
$this->validate_email($this->_str_to_array($replyto));
}
if ($name == '')
{
$name = $replyto;
}
if (strncmp($name, '"', 1) != 0)
{
$name = '"'.$name.'"';
}
$this->_set_header('Reply-To', $name.' <'.$replyto.'>');
$this->_replyto_flag = TRUE;
return $this;
}
// --------------------------------------------------------------------
/**
* Set Recipients
*
* #access public
* #param string
* #return void
*/
public function to($to)
{
$to = $this->_str_to_array($to);
$to = $this->clean_email($to);
if ($this->validate)
{
$this->validate_email($to);
}
if ($this->_get_protocol() != 'mail')
{
$this->_set_header('To', implode(", ", $to));
}
switch ($this->_get_protocol())
{
case 'smtp' :
$this->_recipients = $to;
break;
case 'sendmail' :
case 'mail' :
$this->_recipients = implode(", ", $to);
break;
}
return $this;
}
// --------------------------------------------------------------------
/**
* Set CC
*
* #access public
* #param string
* #return void
*/
public function cc($cc)
{
$cc = $this->_str_to_array($cc);
$cc = $this->clean_email($cc);
if ($this->validate)
{
$this->validate_email($cc);
}
$this->_set_header('Cc', implode(", ", $cc));
if ($this->_get_protocol() == "smtp")
{
$this->_cc_array = $cc;
}
return $this;
}
// --------------------------------------------------------------------
/**
* Set BCC
*
* #access public
* #param string
* #param string
* #return void
*/
public function bcc($bcc, $limit = '')
{
if ($limit != '' && is_numeric($limit))
{
$this->bcc_batch_mode = TRUE;
$this->bcc_batch_size = $limit;
}
$bcc = $this->_str_to_array($bcc);
$bcc = $this->clean_email($bcc);
if ($this->validate)
{
$this->validate_email($bcc);
}
if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))
{
$this->_bcc_array = $bcc;
}
else
{
$this->_set_header('Bcc', implode(", ", $bcc));
}
return $this;
}
// --------------------------------------------------------------------
Could you please try below that code in your any controller index function and run it.
$this->load->library('email');
$this->email->from('your#example.com', 'Your Name');
$this->email->to('someone#example.com');
$this->email->cc('another#another-example.com');
$this->email->bcc('them#their-example.com');
$this->email->subject('Email Test');
$this->email->message('Testing the email class.');
$this->email->send();
echo $this->email->print_debugger();
Simple var $bcc_batch_mode = TRUE;
Edit FALSE to TRUE and give a try!!
My host confirmed that Zend 2.3 is installed. I then proceeded to check the installation was working by uploading this script:
http://www.jarodmorris.com/zend_check.php
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license#zend.com so we can send you a copy immediately.
*
* #category Zend
* #package Zend_Gdata
* #subpackage Demos
* #copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* Simple class to verify that the server that this is run on has a correct
* installation of the Zend Framework Gdata component.
*/
class InstallationChecker {
const CSS_WARNING = '.warning { color: #fff; background-color: #AF0007;}';
const CSS_SUCCESS = '.success { color: #000; background-color: #69FF4F;}';
const CSS_ERROR = '.error { color: #fff; background-color: #FF9FA3;}';
const PHP_EXTENSION_ERRORS = 'PHP Extension Errors';
const PHP_MANUAL_LINK_FRAGMENT = 'http://us.php.net/manual/en/book.';
const PHP_REQUIREMENT_CHECKER_ID = 'PHP Requirement checker v0.1';
const SSL_CAPABILITIES_ERRORS = 'SSL Capabilities Errors';
const YOUTUBE_API_CONNECTIVITY_ERRORS = 'YouTube API Connectivity Errors';
const ZEND_GDATA_INSTALL_ERRORS = 'Zend Framework Installation Errors';
const ZEND_SUBVERSION_URI = 'http://framework.zend.com/download/subversion';
private static $REQUIRED_EXTENSIONS = array(
'ctype', 'dom', 'libxml', 'spl', 'standard', 'openssl');
private $_allErrors = array(
self::PHP_EXTENSION_ERRORS => array(
'tested' => false, 'errors' => null),
self::ZEND_GDATA_INSTALL_ERRORS => array(
'tested' => false, 'errors' => null),
self::SSL_CAPABILITIES_ERRORS => array(
'tested' => false, 'errors' => null),
self::YOUTUBE_API_CONNECTIVITY_ERRORS => array(
'tested' => false, 'errors' => null)
);
private $_sapiModeCLI = null;
/**
* Create a new InstallationChecker object and run verifications.
* #return void
*/
public function __construct()
{
$this->determineIfInCLIMode();
$this->runAllVerifications();
$this->outputResults();
}
/**
* Set the sapiModeCLI variable to true if we are running CLI mode.
*
* #return void
*/
private function determineIfInCLIMode()
{
if (php_sapi_name() == 'cli') {
$this->_sapiModeCLI = true;
}
}
/**
* Getter for sapiModeCLI variable.
*
* #return boolean True if we are running in CLI mode.
*/
public function runningInCLIMode()
{
if ($this->_sapiModeCLI) {
return true;
} else {
return false;
}
}
/**
* Run verifications, stopping at each step if there is a failure.
*
* #return void
*/
public function runAllVerifications()
{
if (!$this->validatePHPExtensions()) {
return;
}
if (!$this->validateZendFrameworkInstallation()) {
return;
}
if (!$this->testSSLCapabilities()) {
return;
}
if (!$this->validateYouTubeAPIConnectivity()) {
return;
}
}
/**
* Validate that the required PHP Extensions are installed and available.
*
* #return boolean False if there were errors.
*/
private function validatePHPExtensions()
{
$phpExtensionErrors = array();
foreach (self::$REQUIRED_EXTENSIONS as $requiredExtension) {
if (!extension_loaded($requiredExtension)) {
$requiredExtensionError = $requiredExtension .
' extension missing';
$documentationLink = null;
if ($requiredExtension != 'standard') {
$documentationLink = self::PHP_MANUAL_LINK_FRAGMENT .
$requiredExtension . '.php';
$documentationLink =
$this->checkAndAddHTMLLink($documentationLink);
} else {
$documentationLink = self::PHP_MANUAL_LINK_FRAGMENT .
'spl.php';
$documentationLink =
$this->checkAndAddHTMLLink($documentationLink);
}
if ($documentationLink) {
$phpExtensionErrors[] = $requiredExtensionError .
' - refer to ' . $documentationLink;
}
}
}
$this->_allErrors[self::PHP_EXTENSION_ERRORS]['tested'] = true;
if (count($phpExtensionErrors) > 0) {
$this->_allErrors[self::PHP_EXTENSION_ERRORS]['errors'] =
$phpExtensionErrors;
return false;
}
return true;
}
/**
* Validate that the Gdata component of Zend Framework is installed
* properly. Also checks that the required YouTube API helper methods are
* found.
*
* #return boolean False if there were errors.
*/
private function validateZendFrameworkInstallation()
{
$zendFrameworkInstallationErrors = array();
$zendLoaderPresent = false;
try {
$zendLoaderPresent = #fopen('Zend/Loader.php', 'r', true);
} catch (Exception $e) {
$zendFrameworkInstallationErrors[] = 'Exception thrown trying to ' .
'access Zend/Loader.php using \'use_include_path\' = true ' .
'Make sure you include the Zend Framework in your ' .
'include_path which currently contains: "' .
ini_get('include_path') . '"';
}
if ($zendLoaderPresent) {
#fclose($zendLoaderPresent);
require_once('Zend/Loader.php');
require_once('Zend/Version.php');
Zend_Loader::loadClass('Zend_Gdata_YouTube');
Zend_Loader::loadClass('Zend_Gdata_YouTube_VideoEntry');
$yt = new Zend_Gdata_YouTube();
$videoEntry = $yt->newVideoEntry();
if (!method_exists($videoEntry, 'setVideoTitle')) {
$zendFrameworkMessage = 'Your version of the ' .
'Zend Framework ' . Zend_Version::VERSION . ' is too old' .
' to run the YouTube demo application and does not' .
' contain the new helper methods. Please check out a' .
' newer version from Zend\'s repository: ' .
checkAndAddHTMLLink(self::ZEND_SUBVERSION_URI);
$zendFrameworkInstallationErrors[] = $zendFrameworkMessage;
}
} else {
if (count($zendFrameworkInstallationErrors) < 1) {
$zendFrameworkInstallationErrors[] = 'Exception thrown trying' .
' to access Zend/Loader.php using \'use_include_path\' =' .
' true. Make sure you include Zend Framework in your' .
' include_path which currently contains: ' .
ini_get('include_path');
}
}
$this->_allErrors[self::ZEND_GDATA_INSTALL_ERRORS]['tested'] = true;
if (count($zendFrameworkInstallationErrors) > 0) {
$this->_allErrors[self::ZEND_GDATA_INSTALL_ERRORS]['errors'] =
$zendFrameworkInstallationErrors;
return false;
}
return true;
}
/**
* Create HTML link from an input string if not in CLI mode.
*
* #param string The error message to be converted to a link.
* #return string Either the original error message or an HTML version.
*/
private function checkAndAddHTMLLink($inputString) {
if (!$this->runningInCLIMode()) {
return $this->makeHTMLLink($inputString);
} else {
return $inputString;
}
}
/**
* Create an HTML link from a string.
*
* #param string The string to be made into link text and anchor target.
* #return string HTML link.
*/
private function makeHTMLLink($inputString)
{
return '<a href="'. $inputString . '" target="_blank">' .
$inputString . '</a>';
}
/**
* Validate that SSL Capabilities are available.
*
* #return boolean False if there were errors.
*/
private function testSSLCapabilities()
{
$sslCapabilitiesErrors = array();
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Http_Client');
$httpClient = new Zend_Http_Client(
'https://www.google.com/accounts/AuthSubRequest');
$response = $httpClient->request();
$this->_allErrors[self::SSL_CAPABILITIES_ERRORS]['tested'] = true;
if ($response->isError()) {
$sslCapabilitiesErrors[] = 'Response from trying to access' .
' \'https://www.google.com/accounts/AuthSubRequest\' ' .
$response->getStatus() . ' - ' . $response->getMessage();
}
if (count($sslCapabilitiesErrors) > 0) {
$this->_allErrors[self::SSL_CAPABILITIES_ERRORS]['errors'] =
$sslCapabilitiesErrors;
return false;
}
return true;
}
/**
* Validate that we can connect to the YouTube API.
*
* #return boolean False if there were errors.
*/
private function validateYouTubeAPIConnectivity()
{
$connectivityErrors = array();
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_YouTube');
$yt = new Zend_Gdata_YouTube();
$topRatedFeed = $yt->getTopRatedVideoFeed();
if ($topRatedFeed instanceof Zend_Gdata_YouTube_VideoFeed) {
if ($topRatedFeed->getTotalResults()->getText() < 1) {
$connectivityErrors[] = 'There was less than 1 video entry' .
' in the \'Top Rated Video Feed\'';
}
} else {
$connectivityErrors[] = 'The call to \'getTopRatedVideoFeed()\' ' .
'did not result in a Zend_Gdata_YouTube_VideoFeed object';
}
$this->_allErrors[self::YOUTUBE_API_CONNECTIVITY_ERRORS]['tested'] =
true;
if (count($connectivityErrors) > 0) {
$this->_allErrors[self::YOUTUBE_API_CONNECTIVITY_ERRORS]['tested'] =
$connectivityErrors;
return false;
}
return true;
}
/**
* Dispatch a call to outputResultsInHTML or outputResultsInText pending
* the current SAPI mode.
*
* #return void
*/
public function outputResults()
{
if ($this->_sapiModeCLI) {
print $this->getResultsInText();
} else {
print $this->getResultsInHTML();
}
}
/**
* Return a string representing the results of the verifications.
*
* #return string A string representing the results.
*/
private function getResultsInText()
{
$output = "== Ran PHP Installation Checker using CLI ==\n";
$error_count = 0;
foreach($this->_allErrors as $key => $value) {
$output .= $key . ' -- ';
if (($value['tested'] == true) && (count($value['errors']) == 0)) {
$output .= "No errors found\n";
} elseif ($value['tested'] == true) {
$output .= "Tested\n";
$error_count = 0;
foreach ($value['errors'] as $error) {
$output .= "Error number: " . $error_count . "\n--" .
$error . "\n";
}
} else {
$output .= "Not tested\n";
}
$error_count++;
}
return $output;
}
/**
* Return an HTML table representing the results of the verifications.
*
* #return string An HTML string representing the results.
*/
private function getResultsInHTML()
{
$html = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" " .
"\"http://www.w3.org/TR/html4/strict.dtd\">\n".
"<html><head>\n<title>PHP Installation Checker</title>\n" .
"<style type=\"text/css\">\n" .
self::CSS_WARNING . "\n" .
self::CSS_SUCCESS . "\n" .
self::CSS_ERROR . "\n" .
"</style></head>\n" .
"<body>\n<table class=\"verification_table\">" .
"<caption>Ran PHP Installation Checker on " .
gmdate('c') . "</caption>\n";
$error_count = 0;
foreach($this->_allErrors as $key => $value) {
$html .= "<tr><td class=\"verification_type\">" . $key . "</td>";
if (($value['tested'] == true) && (count($value['errors']) == 0)) {
$html .= "<td class=\"success\">Tested</td></tr>\n" .
"<tr><td colspan=\"2\">No errors found</td></tr>\n";
} elseif ($value['tested'] == true) {
$html .= "<td class=\"warning\">Tested</td></tr>\n";
$error_count = 0;
foreach ($value['errors'] as $error) {
$html .= "<tr><td class=\"error\">" . $error_count . "</td>" .
"<td class=\"error\">" . $error . "</td></tr>\n";
}
} else {
$html .= "<td class=\"warning\">Not tested</td></tr>\n";
}
$error_count++;
}
$html .= "</body></html>";
return $html;
}
}
$installationChecker = new InstallationChecker();
Go to the above link to see the results. Specifically, I'm interested in this error message:
Exception thrown trying to access Zend/Loader.php using 'use_include_path' = true.
Make sure you include Zend Framework in your include_path which currently contains:
.:/usr/lib/php:/usr/local/lib/php
Here is the link to my php info printout: http://www.jarodmorris.com/cms/phpinfo.php
I've obtained the Zend Framework from the zend website and uploaded it to a /zend folder on my website. For whatever reason, my host won't give me access to the php.ini file. I have purchased a reseller account with my host.
I'm doing all of this because I want to integrate Google Calendar API into an application I'm building on one of my websites. Maybe there is a simpler solution to my ultimate goal, but I don't see it.
Thanks for pointing me in the right direction.
EDITED TO SHOW CURRENT PHP CODE WHERE INCLUDE IS CONCERNED:
set_include_path(get_include_path() . PATH_SEPARATOR . "/home/jarodmo/public_html/zend/library");
echo get_include_path();
echo "<br>";
///home/jarodmo/public_html/zend/library/Zend
Add the dir to your include path:
set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/whatever/your/zend/dir/is');
I keep getting the following error while trying to using __toString():
Catchable fatal error: Object of class Address could not be converted
to string in C:wamp\www\demo.php on line 36
Where did I go wrong?
demo.php
echo '<h2>Instantiating Address</h2>';
$address = new Address;
echo '<h2>Empty Address</h2>';
echo '<tt><pre>' . var_export($address, TRUE) . '</pre></tt>';
echo '<h2>Setting properties...</h2>';
$address->street_address_1 = '555 Fake Street';
$address->city_name = 'Townsville';
$address->subdivision_name = 'State';
$address->postal_code = '12345';
$address->country_name = 'United States of America';
echo '<tt><pre>' . var_export($address, TRUE) . '</pre></tt>';
echo '<h2>Displaying address ...</h2>';
echo $address->display();
echo '<h2>Testing magic __get and __set</h2>';
unset($address->postal_code);
echo $address->display();
echo '<h2>Testing Address __construct with an array</h2>';
$address_2 = new Address(array(
'street_address_1' => '123 Phony Ave',
'city_name' => 'Villageland',
'subdivision_name' => 'Region',
'postal_code' => '67890',
'country_name' => 'Canada',
));
echo $address_2->display();
echo '<h2>Address __toString</h2>';
echo $address_2;
?>
oop.php
<!DOCTYPE html>
<html>
<head><title>OOP</title></head>
<body>
<?php
class Address {
public $street_address_1;
public $street_address_2;
public $city_name;
public $subdivision_name;
public $country_name;
protected $_postal_code;
// Primary key of an address
protected $_address_id;
// When the recorded created and last updated
protected $_time_created;
protected $_time_updated;
/*
Constructor
#param array data optional array of property names
*/
function __construct($data = array()) {
$this->_time_created = time();
// Ensure that the address can be populated.
if(!is_array($data)){
trigger_error('Unable to construct address with a ' . get_class($name));
}
// If there is at lease one value, populate the Address with it
if(count($data) > 0) {
foreach($data as $name => $value){
// Special case for protected properties
if(in_array($name, array(
'time_created',
'time_updated',
))){
$name = '_' . $name;
}
$this->$name = $value;
}
}
}
/*
Magic __get
#param string $name
#return mixed
*/
function __get($name){
// Postal code lookup if unset.
if (!$this->_postal_code){
$this->_postal_code = $this->_postal_code_guess();
}
/*
Magin __set.
#param string $name
#param mixed $value
*/
function __set($name, $value){
// Allow anything to set the postal code.
if ('postal_code' == $name){
$this->$name = $value;
return;
}
// Unable to access property; trigger error,
trigger_error('Undefined or unallowed property via __set(): ' . $name);
}
/*
Magic __toString
#return string
*/
function __toString() {
return $this->display();
}
$protected_property_name = '_' . $name;
if(property_exists($this, $protected_property_name)){
return $this->$protected_property_name;
}
// unable to access property; trigger error
trigger_error('Undefined_property via __get: ' . $name);
return NULL;
}
/*
Guess the postal code given the subdivision and city name.
#todo Replace with a database lookup
#return string
*/
protected function _postal_code_guess(){
return 'LOOKUP';
}
/*
display an address in HTML
return string.
*/
function display(){
$output = '';
// Street address
$output .= $this->street_address_1;
if ($this->street_address_2){
$output .= '<br />' . $this->Street_address_2;
}
// City, Subdivision Postal
$output .= '<br />';
$output .= $this->city_name . ', ' . $this->subdivision_name;
$output .= ' ' . $this->postal_code;
// Country
$output .= '<br />';
$output .= $this->country_name;
return $output;
}
}
?>
</body>
</html>
function __get() isn't properly closed. I`ve removed some code to make it work. Check for differences.
<?php
class Address {
public $street_address_1;
public $street_address_2;
public $city_name;
public $subdivision_name;
public $country_name;
protected $_postal_code;
// Primary key of an address
protected $_address_id;
// When the recorded created and last updated
protected $_time_created;
protected $_time_updated;
/*
Constructor
#param array data optional array of property names
*/
function __construct($data = array()) {
$this->_time_created = time();
// Ensure that the address can be populated.
if(!is_array($data)){
trigger_error('Unable to construct address with a ' . get_class($name));
}
// If there is at lease one value, populate the Address with it
if(count($data) > 0) {
foreach($data as $name => $value){
// Special case for protected properties
if(in_array($name, array(
'time_created',
'time_updated',
))){
$name = '_' . $name;
}
$this->$name = $value;
}
}
}
/*
Magic __get
#param string $name
#return mixed
*/
function __get($name){
// Postal code lookup if unset.
if (!$this->_postal_code){
$this->_postal_code = $this->_postal_code_guess();
}
$protected_property_name = '_' . $name;
if(property_exists($this, $protected_property_name)){
return $this->$protected_property_name;
}
// unable to access property; trigger error
trigger_error('Undefined_property via __get: ' . $name);
return NULL;
}
/*
Magin __set.
#param string $name
#param mixed $value
*/
function __set($name, $value){
// Allow anything to set the postal code.
if ('postal_code' == $name){
$this->$name = $value;
return;
}
// Unable to access property; trigger error,
trigger_error('Undefined or unallowed property via __set(): ' . $name);
}
/*
Magic __toString
#return string
*/
function __toString() {
return $this->display();
}
/*
Guess the postal code given the subdivision and city name.
#todo Replace with a database lookup
#return string
*/
protected function _postal_code_guess(){
return 'LOOKUP';
}
/*
display an address in HTML
return string.
*/
function display(){
$output = '';
// Street address
$output .= $this->street_address_1;
if ($this->street_address_2){
$output .= '<br />' . $this->Street_address_2;
}
// City, Subdivision Postal
$output .= '<br />';
$output .= $this->city_name . ', ' . $this->subdivision_name;
$output .= ' ' . $this->postal_code;
// Country
$output .= '<br />';
$output .= $this->country_name;
return $output;
}
}
Some other frameworks have a link helper like output_link('anchor', 'destination'); to replace the need to type into the template. Does Zend have something similar? and do I have to declare the link in the action first before I can use it in the viewer?
Zend_View_Helper_Url can generate URL in view, take a look on its API doc
http://framework.zend.com/apidoc/core/Zend_View/Helper/Zend_View_Helper_Url.html
I am not sure if Zend has this, but all you would need to do is create your own outputLink in the View Helper (applications/views/helpers/) and set it up how you want to, should be pretty trivial.
class Zend_View_Helper_OutputLink extends Zend_View_Helper_Abstract
{
public function outputLink($anchor, $description)
{
return '' . $description . '';
}
}
Just modify it how you want to. And you would call it in your view like below:
<span><?php $this->outputLink('test.html', 'Test Me!'); ?> </span>
Here's my anchor element view helper for zend. You need to use my image element view helper or remove the part of the code that uses it in case you don't like it. Of course, you're free to modify name and whatever else you wish.
require_once 'Zend/View/Helper/HtmlElement.php';
class Ecoweb_View_Helper_AnchorElement extends Zend_View_Helper_HtmlElement {
/**
*
* #param string $url
* #param string $content
* #param array|string $attribs
* #return string
*/
public function anchorElement($url, $content = '', $attribs = null)
{
if (is_array($url)) {
$reset = isset($url[2]) ? $url[2] : false;
$encode = isset($url[3]) ? $url[3] : false;
$url = $this->view->url($url[0], $url[1], $reset, $encode);
} else {
$url = $this->view->baseUrl($url);
}
if (is_array($attribs)) {
$attribs = $this->_htmlAttribs($attribs);
} else {
$attribs = empty($attribs) ? '' : ' '.$attribs;
}
if (is_array($content) && isset($content['src'])) {
$src = $content['src'];
$alt = isset($content['alt']) ? $content['alt'] : null;
$imgAttribs = isset($content['attribs']) ? $content['attribs'] : array();
$content = $this->view->imgElement($src, $alt, $imgAttribs);
}
$content = empty($content) ? $url : $this->view->escape($content);
$xhtml = '<a '
. 'href="'.$url.'"'
. $attribs
. '>'
. $content
. '</a>';
return $xhtml;
}
}
Here's the image element view helper:
<?php
require_once 'Zend/View/Helper/HtmlElement.php';
class Ecoweb_View_Helper_ImgElement extends Zend_View_Helper_HtmlElement {
/**
*
* #param string $src
* #param string $alt
* #param array|string $attribs
* #return string
*/
public function imgElement($src, $alt = '', $attribs = null)
{
$src = $this->view->baseUrl($src);
if (is_array($attribs)) {
$attribs = $this->_htmlAttribs($attribs);
} else {
$attribs = empty($attribs) ? '' : ' '.$attribs;
}
$alt = $this->view->escape($alt);
$xhtml = '<img '
. 'src="'.$src.'" '
. 'alt="'.$alt.'"'
. $attribs
. $this->getClosingBracket();
return $xhtml;
}
}
Use cases:
echo $this->anchor('/mycontroller/myaction');
// output: /mycontroller/myaction
echo $this->anchor('/mycontroller/myaction', 'My anchor content', 'rel="nofollow"');
// output: My anchor content
echo $this->anchor('/mycontroller/myaction', 'My anchor content', 'rel="nofollow"');
// output: My anchor content
// when baseUrl is http://mydomain.com
echo $this->anchor(array(array('controller' => 'mycontroller', 'action' => 'myaction'), 'myroute'), 'My anchor content', array('rel' => 'nofollow'));
// output: My anchor content
echo $this->anchor('/mycontroller/myaction', array('src' => '/uploads/myimag.png'));
// output: <img src="/uploads/myimag.png" alt="">
// when you have an html doctype
echo $this->anchor('/mycontroller/myaction', array('src' => '/uploads/myimag.png', 'alt'=>'My alt text', array('width' => '100')));
// output: <img src="/uploads/myimag.png" alt="My alt text" width="100" />
// when you have an xhtml doctype
Well, Zend's url helper kind of thing kinda sucks. This is the only thing that pains me while developing apps in zend. In Codeigniter url helper used to come very handy. Zend has very limited resources in case of this. I had to port CI's url helper to use in my Zend Apps. And moreover, Symfony doesn't have that many helper methods like CI has and I'm not sure why.
No, you have to make one.