Last active
August 22, 2016 02:24
-
-
Save jthurteau/587ef87b81e1491f64c2736c24b68068 to your computer and use it in GitHub Desktop.
pattern examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// example of how this would get called: | |
// during bootstrap: | |
// configuration specifies a "Messenger" resource with property enabled as true/false | |
class Bootstrap { | |
protected function _initMessenger($config){ | |
Messenger_Root::init($config); // values from config are strings, hence the Saf_Filter_Truthy::filter call in ::init | |
} | |
} | |
// ... | |
// also during boot strap, used to keep the numbers used in auto-generating sequence values lower | |
Saf_Ical::setBaseTime(Ems::getMinTimestamp()); | |
// ... | |
// when sending a message with ical data | |
Messenger_Root::get()->sendIcal($reservationCode, $username, | |
'NCSU Libraries Room Reservation, [[$room]] for [[$date]] [[$year]]' , | |
'This message is to confirm your reservation for: | |
[[$location]] | |
at [[$userStart]] - [[$userEnd]] | |
on [[$date]] [[$year]] | |
If you need to modify or delete this reservation, | |
please return to the room reservation system: | |
[[$url]] | |
A calendar invitation is attached to this email, which you can add to your Google Calendar and share with others. | |
' | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Encapsulates our business logic behind using the EMS System, Proxy and Facade to the API | |
*/ | |
class Ems { | |
public static function getBookingInfo($bookingId, $username) | |
{ | |
$userId = self::getUserId($username); | |
$booking = self::$_api->getBooking($bookingId); | |
if ($booking) { | |
$filteredBookings = self::tidyBookings(array($bookingId => $booking)); | |
return $filteredBookings[$bookingId]; | |
} else { | |
return NULL; | |
} | |
} | |
public static function tidyBookings($bookings, $sortOrder = NULL) | |
{ | |
foreach($bookings as $bookingId => $bookingData) { | |
if (!array_key_exists('code', $bookings[$bookingId])) {//#NOTE try to avoid filtering twice | |
$bookings[$bookingId]['code'] = "{$bookingData['reservationId']}/{$bookingId}"; | |
$bookings[$bookingId]['date'] = | |
Saf_Time::modify( | |
strtotime($bookings[$bookingId]['date']), | |
Saf_Time::MODIFIER_START_DAY | |
); | |
$bookings[$bookingId]['originalStart'] = $bookings[$bookingId]['start']; | |
$bookings[$bookingId]['originalEnd'] = $bookings[$bookingId]['end']; | |
$bookings[$bookingId]['dateString'] = | |
date(Ems::EMS_DATE_FORMAT, $bookings[$bookingId]['date']); | |
$bookings[$bookingId]['userDate'] = | |
date(Ems::EMS_USER_DATECALENDAR_FORMAT, $bookings[$bookingId]['date']); | |
$bookings[$bookingId]['userYear'] = | |
date('Y', $bookings[$bookingId]['date']); | |
$bookings[$bookingId]['userMonth'] = | |
date('M', $bookings[$bookingId]['date']); | |
$bookings[$bookingId]['userDay'] = | |
date('j', $bookings[$bookingId]['date']); | |
$bookings[$bookingId]['startString'] = | |
substr( | |
$bookings[$bookingId]['start'], | |
strpos($bookings[$bookingId]['start'], 'T') + 1 | |
); | |
$bookings[$bookingId]['fullStart'] = | |
strtotime($bookings[$bookingId]['start']); | |
$bookings[$bookingId]['userStart'] = date( | |
Ems::EMS_USER_TIME_FORMAT, | |
$bookings[$bookingId]['fullStart'] | |
); | |
$bookings[$bookingId]['start'] = | |
Saf_Time::hourStringToStamp($bookings[$bookingId]['start']); | |
$bookings[$bookingId]['endString'] = | |
substr( | |
$bookings[$bookingId]['end'], | |
strpos($bookings[$bookingId]['end'], 'T') + 1 | |
); | |
$bookings[$bookingId]['fullEnd'] = | |
strtotime($bookings[$bookingId]['end']); | |
$bookings[$bookingId]['userEnd'] = date( | |
Ems::EMS_USER_TIME_FORMAT, | |
$bookings[$bookingId]['fullEnd'] + 1 | |
); | |
$bookings[$bookingId]['truncatedEnd'] = | |
Saf_Time::hourStringToStamp($bookings[$bookingId]['end']); | |
$bookings[$bookingId]['crossesMidnight'] = | |
$bookings[$bookingId]['fullEnd'] - $bookings[$bookingId]['date'] | |
> Saf_Time::MAX_HOUR_STAMP; | |
$bookings[$bookingId]['end'] = | |
$bookings[$bookingId]['crossesMidnight'] | |
? $bookings[$bookingId]['truncatedEnd'] + Saf_Time::MAX_HOUR_STAMP + 1 | |
: $bookings[$bookingId]['truncatedEnd']; | |
$bookings[$bookingId]['userEventType'] = | |
self::getUserEventTypeLabel($bookings[$bookingId]['eventType']); | |
$bookings[$bookingId]['userStatus'] = | |
self::getUserStatusLabel($bookings[$bookingId]['status']); | |
$bookings[$bookingId]['userRoom'] = | |
self::getUserRoomLabel($bookings[$bookingId]['roomId']); | |
$bookings[$bookingId]['userLocation'] = | |
self::getUserLocationLabel($bookings[$bookingId]['roomId']); | |
$bookings[$bookingId]['userFloor'] = | |
self::getRoomDetails($bookings[$bookingId]['roomId'], 'floor'); | |
$bookings[$bookingId]['userBuilding'] = | |
self::getUserBuildingLabel($bookings[$bookingId]['buildingId']); | |
$bookings[$bookingId]['roomNumber'] = | |
self::getRoomNumber($bookings[$bookingId]['roomId']); | |
$bookings[$bookingId]['roomType'] = | |
self::getRoomDetails($bookings[$bookingId]['roomId'], 'type'); | |
$bookings[$bookingId]['roomCapacity'] = | |
self::getRoomDetails($bookings[$bookingId]['roomId'], 'capacity'); | |
$bookings[$bookingId]['userEmail'] = 'not loaded'; | |
$bookings[$bookingId]['userId'] = 'not loaded'; | |
$bookings[$bookingId]['userSortName'] = 'not loaded'; | |
$bookings[$bookingId]['username'] = 'not loaded'; | |
$bookings[$bookingId]['userLastname'] = 'not loaded'; | |
$bookings[$bookingId]['userFirstname'] = 'not loaded'; | |
$bookings[$bookingId]['userFullname'] = 'not loaded'; | |
} | |
} | |
return | |
is_null($sortOrder) | |
? $bookings | |
: self::chronoSortBookings($bookings, $sortOrder); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Implements interface to the EMS API and mediates requests to optimize performance between API calls and cache. | |
*/ | |
class Ems_Api { | |
public function getBooking($bookingId) | |
{ | |
$params = array('bookingId' => $bookingId); | |
$responseKeys = array( | |
'date' => 'BookingDate', | |
'start' => 'TimeEventStart', | |
'end' => 'TimeEventEnd', | |
'groupId' => 'GroupID', | |
'description' => 'EventName', | |
'reservationId' => 'ReservationID', | |
'eventType' => 'EventTypeID', | |
'status' => 'StatusID', | |
'statusType' => 'StatusTypeID', | |
'roomId' => 'RoomID', | |
'buildingId' => 'BuildingID', | |
'templateId' => 'WebProcessTemplateID' | |
); | |
return $this->_simpleSend('getBooking', $responseKeys, self::API_KEY_SINGLETON, $params); | |
} | |
private function _simpleSend($call, $keys = NULL, $idKey = self::API_KEY_DEFAULT, $params = NULL) | |
{ | |
if (is_null($idKey)) { | |
$idKey = self::API_KEY_DEFAULT; | |
} | |
$currentKey = | |
$idKey === self::API_KEY_INTERATIVE | |
|| $idKey === self::API_KEY_SINGLETON | |
? 0 | |
: $idKey; | |
$response = array(); | |
$message = new Saf_Message_Template($call); | |
$messageParams = (is_null($params))? array(): $params; | |
$messageParams['auth'] = $this->getAuthString(); | |
$dereferenceConfig = array( | |
'params' => $messageParams | |
); | |
$dereferencedMessage = $message->get($dereferenceConfig); | |
$rawResponse = $this->send($dereferencedMessage); | |
Saf_Profile::action('API', $call, array('size' => $rawResponse['length'])); | |
$finalPattern = | |
$idKey === self::API_KEY_SINGLETON | |
? self::API_PARSE_PATTERN_SINGLETON | |
: self::API_PARSE_PATTERN_NONE; | |
$payload = $this->parseResponse($rawResponse, $finalPattern); | |
if ($payload) { | |
if ($finalPattern == self::API_PARSE_PATTERN_SINGLETON) { | |
$payload = array($payload); | |
} | |
foreach ($payload as $item) { | |
if ( | |
( | |
is_array($item) | |
|| !$keys | |
) && ( | |
$idKey === self::API_KEY_SINGLETON | |
|| $idKey === self::API_KEY_INTERATIVE | |
|| array_key_exists($currentKey, $item) | |
) | |
) { | |
$itemKey = | |
$idKey === self::API_KEY_SINGLETON | |
|| $idKey === self::API_KEY_INTERATIVE | |
? $currentKey | |
: $item[$currentKey]; | |
$response[$itemKey] = $keys ? array() : $item; | |
if ($keys) { | |
foreach($keys as $keyTransform => $key){ | |
$targetKey = is_numeric($keyTransform) ? $key : $keyTransform; | |
$response[$itemKey][$targetKey] = | |
array_key_exists($key, $item) | |
? $item[$key] | |
: NULL; | |
} | |
} | |
if ($idKey === self::API_KEY_INTERATIVE) { | |
$currentKey++; | |
} | |
} | |
} | |
} | |
return | |
$finalPattern == self::API_PARSE_PATTERN_SINGLETON | |
? (array_key_exists(0, $response) ? $response[0] : NULL) | |
: $response; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Model object that knows how to generate a simple representation (memento) of an event | |
*/ | |
class Event_Model { | |
public static function get($identifier, $parameters = array()) | |
{ | |
$codeParts = explode('/',$identifier, 2); | |
if ($codeParts && count($codeParts) == 2) { | |
$bookingId = $codeParts[1]; | |
$username = | |
array_key_exists($parameters, $parameters) | |
? $parameters['username'] | |
: NULL; | |
$reservation = Ems::getBookingInfo($bookingId, $username); | |
if (!$reservation) { | |
throw new Ems_Exception_Reservation_404("Unable to load booking {$bookingId}"); | |
} | |
$screened = Ems::screenBookings( | |
array($bookingId => $reservation), | |
$username | |
); | |
$reservation = $screened[$bookingId]; | |
} | |
return $reservation; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Class to build an iCal document from an map of data representing an event. | |
* This is used for both generating e-mail attachments, and documents served as | |
* a web service. | |
*/ | |
class Saf_Ical { | |
const METHOD_REQUEST = 'Request'; | |
const METHOD_PUBLISH = 'Publish'; | |
const METHOD_CANCEL = 'Cancel'; | |
const OUTPUT_COL_MAX = 70; | |
const OUTPUT_ESCAPE_CHARS = ':;,\\'; | |
const OUTPUT_REMOVE_CHARS = ""; | |
const OUTPUT_DATESTAMP = 'Ymd\THis\Z'; | |
const AUTO_SEQUENCE = '*'; | |
const MIME_TYPE = 'text/calendar'; | |
protected $_ical = ''; | |
protected $_attachment = ''; | |
protected $_baseTime = NULL; | |
protected $_timeInterval = 60; | |
protected $_method = self::METHOD_REQUEST; | |
protected $_id = NULL; | |
protected $_filename = 'event.ics'; | |
protected $_hostId = ''; | |
protected $_productId = ''; | |
protected $_lang = 'EN'; | |
protected $_version = '2.0'; | |
protected static $_systemBaseTime = 0; | |
protected static $_itemProps = array( | |
'VEVENT' => array( | |
'UID' => 1, | |
'ORGANIZER' => '?', | |
'ATTENDEE[]' => '*', | |
'DTSTART' => 1, | |
'DTEND' => 1, | |
'DTSTAMP' => 1, | |
'LOCATION' => '?', | |
'SEQUENCE' => '?', | |
'LAST-MODIFIED' => '?', | |
'SUMMARY' => 1, | |
'DESCRIPTION' => '?', | |
'URL' => '?', | |
'STATUS' => '?', | |
'CATEGORIES' => '?' | |
) | |
); | |
protected static $_propHelperMap = array( | |
'fullStart' => 'DTSTART', | |
'start' => 'DTSTART', | |
'fullEnd' => 'DTEND', | |
'end' => 'DTEND', | |
'now' => 'DTSTAMP', | |
'modified' => 'LAST-MODIFIED', | |
'title' => 'SUMMARY', | |
'sequence' => 'SEQUENCE', | |
'name' => 'SUMMARY', | |
'description' => 'SUMMARY', | |
'userEmail' => 'ATTENDEE', | |
'attendeeEmail' => 'ATTENDEE', | |
'ownerEmail' => 'ORGANIZER', | |
'userLocation' => 'LOCATION', | |
); | |
public function __construct($config = array()) | |
{ | |
$this->_hostId = Saf_Array::extract('hostId', $config, APPLICATION_ENV . '.' . APPLICATION_HOST); | |
$this->_productId = Saf_Array::extract('productId', $config, APPLICATION_ID . '.' . APPLICATION_INSTANCE); | |
$this->_baseTime = (int)Saf_Array::extract('baseTime', $config, self::$_systemBaseTime); | |
$this->_timeInterval = (int)Saf_Array::extract('timeInterval', $config, $this->_timeInterval); | |
$this->_method = Saf_Array::extractOptional('method', $config); | |
$this->_id = Saf_Array::extractOptional('id', $config); | |
switch ($this->_method) { | |
case self::METHOD_REQUEST: | |
$this->setMethodRequest(); | |
break; | |
case self::METHOD_PUBLISH: | |
$this->setMethodPublish(); | |
break; | |
case self::METHOD_CANCEL: | |
$this->setMethodCancel(); | |
break; | |
} | |
if (!is_null($this->_id) && (!is_array($this->_id) || count($this->_id) > 0)) { | |
$this->generate($config); | |
} | |
} | |
public function __toString() | |
{ | |
return $this->getIcal(); | |
} | |
public function setMethodRequest() | |
{ | |
$this->_method = self::METHOD_REQUEST; | |
} | |
public function setMethodPublish() | |
{ | |
$this->_method = self::METHOD_PUBLISH; | |
} | |
public function setMethodCancel() | |
{ | |
$this->_method = self::METHOD_PUBLISH; | |
} | |
public function generate($data) | |
{ | |
if(is_array($this->_id)) { | |
$this->_generateMulti($data); | |
} else { | |
$this->_generate($data); | |
} | |
} | |
public function getIcal() | |
{ | |
return $this->_ical; | |
} | |
public function getAttachment() | |
{ | |
return $this->_attachment; | |
} | |
protected function _getHeader() | |
{ | |
$method = strtoupper($this->_method); | |
$product = self::escapeText("{$this->_productId}//{$this->_hostId}"); | |
$url = ''; | |
return "BEGIN:VCALENDAR\n" | |
. "METHOD:{$method}\n" | |
. "PRODID:-//{$product}//{$this->_lang}\n" | |
. "VERSION:{$this->_version}\n" | |
. $url; | |
} | |
protected function _getFooter() | |
{ | |
return "END:VCALENDAR"; | |
} | |
protected function _generate($data, $id = NULL) | |
{ | |
$type = 'VEVENT'; //#TODO #2.0.0 support other types | |
$itemData = $data; | |
$this->_ical = | |
(is_null($id) ? $this->_getHeader() : '') | |
. "BEGIN:{$type}\n" | |
. $this->_renderItem($type, is_null($id) ? $this->_id : $id , $itemData) | |
. "END:{$type}\n" | |
. (is_null($id) ? $this->_getFooter() : ''); | |
$this->_generateAttachment(); | |
} | |
protected function _generateMulti($data) | |
{ | |
$items = array(); | |
foreach($this->_id as $id => $item) { | |
$items[] = $this->_generate($item, $id); | |
} | |
$this->_ical = | |
$this->_getHeader() | |
. implode("\n", $items) | |
. $this->_getFooter(); | |
$this->_generateAttachment(); | |
} | |
protected function _renderItem($type, $id, $data) | |
{ | |
$out = ''; | |
$outType = strtolower(substr($type, 1)); | |
$outProp = "$prop:"; | |
$dateStamp = gmdate(self::OUTPUT_DATESTAMP, Saf_Time::time()); | |
$version = $this->getVersion($data); | |
$atProps = 'CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE'; //or just ROLE=REQ-PARTICIPANT; | |
$uid = "{$outType}{$id}@{$this->_hostId}"; | |
//#TODO #2.0.0 see what more advanced attendee properties we can support... | |
foreach(self::$_itemProps[$type] as $prop => $card) { | |
$value = NULL; | |
$propKey = array_key_exists($prop, $data) | |
? $prop | |
: $this->_resolvePropKey($prop, $data); | |
$outProp = "$prop:"; | |
switch ($prop){ | |
case 'ORGANIZER': | |
case 'ATTENDEE': | |
$attendeeMail = | |
$propKey | |
&& array_key_exists($propKey, $data) | |
? $data[$propKey] | |
: NULL; | |
$cnSource = | |
array_key_exists('USER:CN', $data) | |
? $data['USER:CN'] | |
: ( | |
array_key_exists('userFullname', $data) | |
? $data['userFullname'] | |
: NULL | |
); | |
if (is_array($attendeeMail)) { | |
foreach($attendeeMail as $email) { | |
$outProp = array(); | |
if ( | |
is_array($cnSource) && array_key_exists($email, $cnSource) | |
) { | |
$cn = ";CN={$cnSource[$email]}"; | |
} else { | |
$cn = ''; | |
} | |
$outProp = 'ATTENDEE;'; | |
$value[] = "{$atProps}{$cn}:MAILTO:{$email}"; | |
} | |
} else if (!is_null($attendeeMail)) { | |
$attendeeCn = | |
is_array($cnSource) | |
? '' | |
: ";CN={$cnSource}"; | |
$outProp = 'ATTENDEE;'; | |
$value = "{$atProps}{$attendeeCn}:MAILTO:{$attendeeMail}"; | |
} | |
break; | |
case 'DTSTAMP': | |
case 'DTSTART': | |
case 'DTEND': | |
case 'LAST-MODIFIED': | |
$value = | |
$propKey | |
&& array_key_exists($propKey, $data) | |
? $data[$propKey] | |
: NULL; | |
if (!is_null($value)) { | |
if (Saf_Time::isTimeStamp($value)) { | |
$value = gmdate(self::OUTPUT_DATESTAMP, $value); | |
} else { | |
//#TODO #2.0.0 detect non-GMT and convert | |
} | |
} else if ($prop == 'DTSTAMP') { | |
$value = gmdate(self::OUTPUT_DATESTAMP, Saf_Time::time()); | |
} | |
break; | |
case 'UID': | |
$value = $uid; | |
break; | |
case 'SEQUENCE': | |
if ( | |
$propKey | |
&& array_key_exists($propKey, $data) | |
&& $data[$propKey] == '*' | |
) { | |
$value = Saf_Time::time() - $this->_baseTime; | |
} else if ( | |
$propKey | |
&& array_key_exists($propKey, $data) | |
) { | |
$value = (int)$data[$propKey]; | |
} | |
break; | |
case 'STATUS': | |
switch (strtoupper($this->_method)) { | |
case 'CANCEL' : | |
$value = | |
$propKey | |
&& array_key_exists($propKey, $data) | |
? strtoupper($data[$propKey]) | |
: NULL; | |
break; | |
case 'PUBLISH' : | |
case 'REQUEST' : | |
default: | |
$value = | |
$propKey | |
&& array_key_exists($propKey, $data) | |
? strtoupper($data[$propKey]) | |
: 'CONFIRMED'; | |
} | |
break; | |
default: | |
if ($propKey && array_key_exists($propKey, $data)) { | |
$value = self::escapeText($data[$propKey]); | |
} | |
} | |
if ($card === '+' || $card === 1) { | |
if (is_null($value)) { | |
throw new Exception("Required value {$prop} missing to generate iCal for {$uid}"); | |
} | |
} else if ($card === '?' || $card === 1) { | |
if (is_array($value)) { | |
throw new Exception("Too many values provided for {$prop} to generate iCal for {$uid}"); | |
} | |
} | |
if (is_array($value) && count($value) > 0) { | |
foreach($value as $subValue) { | |
$out .= "{$outProp}{$subValue}\n"; | |
} | |
} else if (!is_array($value) && !is_null($value)) { | |
$out .= "{$outProp}{$value}\n"; | |
} | |
} | |
return $out; | |
} | |
protected function _resolvePropKey($key, $data) | |
{ | |
foreach(self::$_propHelperMap as $dataKey => $propKey){ | |
if ( | |
array_key_exists($dataKey, $data) | |
&& self::$_propHelperMap[$dataKey] == $key | |
) { | |
return $dataKey; | |
} | |
} | |
return NULL; | |
} | |
protected function _generateAttachment() | |
{ | |
$this->_attachment = new Zend_Mime_Part($this->_ical); | |
$method = strtoupper($this->_method); | |
$this->_attachment->type = "text/calendar; method={$method}"; | |
$this->_attachment->disposition = Zend_Mime::DISPOSITION_INLINE; | |
$this->_attachment->encoding = Zend_Mime::ENCODING_8BIT; | |
$this->_attachment->filename = $this->_filename; | |
} | |
public static function escapeText($string) | |
{ | |
$removeChars = str_split(self::OUTPUT_REMOVE_CHARS); | |
$filtered = addcslashes( | |
str_replace($removeChars, '', $string), | |
self::OUTPUT_ESCAPE_CHARS | |
); | |
$lines = str_split($filtered, self::OUTPUT_COL_MAX); | |
if (strlen($lines[count($lines) - 1]) == 0) { //#TODO #2.0.0 research if this is needed | |
unset($lines[count($lines) - 1]); | |
} | |
return implode("\n ", $lines); | |
} | |
public function getVersion() | |
{ | |
return $this->_version; | |
} | |
public function getTimedVersion() | |
{ | |
$versionTime = time() - $this->_baseTime; | |
return ( | |
$versionTime - ($versionTime % $this->_timeInterval) | |
) / $this->_timeInterval; | |
} | |
public static function setBaseTime($timestamp) | |
{ | |
self::$_systemBaseTime = $timestamp; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Mediator class that can create and handle different message types. | |
*/ | |
class Messenger | |
{ | |
protected $_name = NULL; | |
protected $_address = NULL; | |
public __construct($config) | |
{ | |
$name = | |
Saf_Array::keyExistsAndNotBlank('name', $config) | |
? trim($config['name']) | |
: NULL; | |
$this->setName($name); | |
$address = | |
Saf_Array::keyExistsAndNotBlank('address', $config) | |
? trim($config['address']) | |
: ''; | |
$this->setAddress($address); | |
} | |
public function setName($name) | |
{ | |
if ($name) { | |
$this->_name = $name; | |
return TRUE; | |
} | |
return FALSE; | |
public function setAddress($address) | |
{ | |
if ($address && !Saf_Filter_Email::filter($config['address'])) { | |
throw new Exception('Invalid Sender Address'); | |
} else if($address){ | |
$this->_address = $address; | |
return TRUE; | |
} | |
return FALSE; | |
} | |
public static function sendIcal($event, $username, $subject, $message, $isUpdate = FALSE) | |
{ | |
$this->_assertReady(); | |
if (!is_array($event)) { | |
$reservationCode = $event; | |
$event = Saf_Model::convert($event, 'event', array('username' => $username)); | |
if ($event['userEmail'] != "{$username}@ncsu.edu") { | |
throw new Ems_Exception_Reservation_403("Attempting to mail reservation {$reservationCode} to wrong user."); | |
} | |
} | |
$email = $event['userEmail']; | |
$name = $event['userFullname']; | |
if ($isUpdate && !array_key_exists('modified', $event) { | |
$event['modified'] = Saf_Time::time(); | |
} | |
$icalEvent = array_merge( | |
$event, | |
array( | |
'method' => Saf_Ical::METHOD_REQUEST, | |
'id' => str_replace('/', '_', $event['code']), | |
'sequence' => Saf_Ical::AUTO_SEQUENCE | |
) | |
); | |
$ical = new Saf_Ical($icalEvent); | |
$url = Zend_Registry::get('siteUrl') . 'reservation'; | |
$message = str_replace( | |
array( | |
'[[$location]]', | |
'[[$userStart]]', | |
'[[$userEnd]]', | |
'[[$date]]', | |
'[[$year]]', | |
'[[$url]]' | |
), array( | |
$event['userLocation'], | |
$event['userStart'], | |
$event['userEnd'], | |
$event['userDate'], | |
$event['userYear'], | |
$url | |
), $message | |
); | |
$subject = str_replace( | |
array( | |
'[[$room]]', | |
'[[$date]]', | |
'[[$year]]' | |
), array( | |
$event['userRoom'], | |
$event['userDate'], | |
$event['userYear'] | |
), $subject | |
); | |
$this->sendMail(array($email, $name), $subject, $message, $ical->getAttachment()); | |
return $this; | |
} | |
public function sendMail($to, $subject, $message, $attachment = NULL) | |
{ | |
$this->_assertReady(); | |
$mail = new Zend_Mail(); | |
$mail->setBodyText($message); | |
$mail->setFrom($this->_name, $this->_address); | |
if (is_array($to)) { | |
$mail->addTo($to, $name); | |
} else { | |
$mail->addTo($to); | |
} | |
$mail->setSubject($subject); | |
if (!is_null($attachment)) { | |
$mail->addAttachment($attachment); | |
} | |
$mail->send(); | |
return $this; | |
} | |
protected _assertReady() | |
{ | |
if (!$this->_name || !$this->_address) { | |
throw new Exception("Attempting to send mail with no sender specified: \"{$this->_name}, {$this->_address}\""); | |
} | |
return $this; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Singleton for a root messenger that can be globally enabled or disabled (e.g. disabled on development). | |
* ::init() gets called during bootstrap, determining if the instance will send any messages or not. | |
*/ | |
abstract class Messenger_Root | |
{ | |
const NEWLINE = "\r\n"; | |
protected static $_enabled = FALSE; | |
protected static $_instance = NULL; | |
public static function init($config) | |
{ | |
if (!is_null(self::$_instance) { | |
return; | |
} | |
if ( | |
$config && array_key_exists('enabled', $config) | |
&& !Saf_Filter_Truthy::filter($config['enabled']) | |
) { | |
self::$_enabled = TRUE; | |
Saf_Profiler::flag('+Messaging'); | |
} else { | |
Saf_Profiler::flag('-Messaging'); | |
return; | |
} | |
$rootMailSender = | |
Saf_Array::keyExistsAndNotBlank('name', $config) | |
? trim($config['name']) | |
: NULL; | |
if (!$rootMailSender) { | |
throw new Saf_Exception_Startup('No Messenger Sender Name'); | |
} | |
$rootMailAddress = | |
Saf_Array::keyExistsAndNotBlank('address', $config) | |
? trim($config['address']) | |
: NULL; | |
if (!$rootMailAddress) { | |
throw new Saf_Exception_Startup('No Messenger Sender Address'); | |
} | |
try{ | |
self::$_instance = new Messenger($config); | |
} catch (Exception $e) { | |
if (!is_a($e, 'Saf_Exception_Startup') { | |
throw new Saf_Exception_Startup('Failed to create Messenger', 0, $e); | |
} | |
throw $e; | |
} | |
} | |
public static function get() | |
{ | |
return self::$_instance; | |
} | |
public static function isEnabled() | |
{ | |
return self::$_enabled; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* class to decouple resolution to a model type from the generation of the memento | |
*/ | |
Saf_Model { | |
public static function convert($identifier, $model, $parameters = array()) | |
{ | |
$className = Saf_Filter_ValidClass(ucfirst($model) . '_Model'); | |
if ($className) { | |
$reflector = new ReflectionClass($className); | |
return $reflector->getMethod('get')->invokeArgs(NULL, array($identifier, $parameters)); | |
} else { | |
throw new Saf_Exception_Reflection("Unable to resolve model: {$model}"); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment