Index: documentation/manual/en/module_specs/Zend_Log-Factory.xml =================================================================== --- documentation/manual/en/module_specs/Zend_Log-Factory.xml (revision 22824) +++ documentation/manual/en/module_specs/Zend_Log-Factory.xml (working copy) @@ -175,12 +175,149 @@ Zend_Log_Writer_Mail Options + + + Zend_Log_Writer_Mail Options - - Zend_Log_Writer_Mail currently (as of 1.10) does not - implement a factory, and will raise an exception if you attempt to instantiate it - via Zend_Log::factory(). - + + + + Option + Data Type + Default Value + Description + + + + + + mail + String + Zend_Mail + + + An Zend_Mail instance + + + + + charset + String + iso-8859-1 + + + Charset of the mail + + + + + from + String or Array + NULL + + + Sender of the mail + + The parameters for Array type are : + + + + email : address of sender + + + + + + name : name of sender + + + + + + + + to + String or Array + NULL + + + Recipient(s) of the mail + + + + + cc + String or Array + NULL + + + Carbon copy recipient(s) of the mail + + + + + bcc + String or Array + NULL + + + Blind carbon copy recipient(s) of the mail + + + + + subject + String + NULL + + + Subject of the mail + + + + + subjectPrependText + String + NULL + + + A summary of number of errors per priority is appended to the + subject of the mail + + + + + layout + String + NULL + + + An Zend_Layout instance + + + + + layoutOptions + Array + NULL + + + See the section + + + + + layoutFormatter + String + NULL + + + An Zend_Log_Formatter_Interface instance + + + + +
Index: tests/Zend/Log/Writer/_files/layout.phtml =================================================================== --- tests/Zend/Log/Writer/_files/layout.phtml (revision 0) +++ tests/Zend/Log/Writer/_files/layout.phtml (revision 0) @@ -0,0 +1 @@ +layout()->events; \ No newline at end of file Index: library/Zend/Log/Writer/Mail.php =================================================================== --- library/Zend/Log/Writer/Mail.php (revision 22797) +++ library/Zend/Log/Writer/Mail.php (working copy) @@ -101,6 +101,18 @@ protected $_subjectPrependText; /** + * MethodMap for Zend_Mail's headers + * + * @var array + */ + protected static $_methodMapHeaders = array( + 'from' => 'setFrom', + 'to' => 'addTo', + 'cc' => 'addCc', + 'bcc' => 'addBcc', + ); + + /** * Class constructor. * * Constructs the mail writer; requires a Zend_Mail instance, and takes an @@ -113,21 +125,129 @@ */ public function __construct(Zend_Mail $mail, Zend_Layout $layout = null) { - $this->_mail = $mail; - $this->_layout = $layout; + $this->_mail = $mail; + if (null !== $layout) { + $this->setLayout($layout); + } $this->_formatter = new Zend_Log_Formatter_Simple(); } - + /** * Create a new instance of Zend_Log_Writer_Mail * * @param array|Zend_Config $config * @return Zend_Log_Writer_Mail - * @throws Zend_Log_Exception */ static public function factory($config) { - throw new Zend_Exception('Zend_Log_Writer_Mail does not currently implement a factory'); + $config = self::_parseConfig($config); + $mail = self::_constructMailFromConfig($config); + $writer = new self($mail); + + if (isset($config['layout']) || isset($config['layoutOptions'])) { + $writer->setLayout($config); + } + if (isset($config['layoutFormatter'])) { + $layoutFormatter = new $config['layoutFormatter']; + $writer->setLayoutFormatter($layoutFormatter); + } + if (isset($config['subjectPrependText'])) { + $writer->setSubjectPrependText($config['subjectPrependText']); + } + + return $writer; + } + + /** + * Set the layout + * + * @param Zend_Layout|array $layout + * @return Zend_Log_Writer_Mail + * @throws Zend_Log_Exception + */ + public function setLayout($layout) + { + if (is_array($layout)) { + $layout = $this->_constructLayoutFromConfig($layout); + } + + if (!$layout instanceof Zend_Layout) { + require_once 'Zend/Log/Exception.php'; + throw new Zend_Log_Exception('Mail must be an instance of Zend_Layout or an array'); + } + $this->_layout = $layout; + + return $this; + } + + /** + * Construct a Zend_Mail instance based on a configuration array + * + * @param array $config + * @return Zend_Mail + */ + protected static function _constructMailFromConfig(array $config) + { + $mailClass = 'Zend_Mail'; + if (isset($config['mail'])) { + $mailClass = $config['mail']; + } + + if (!array_key_exists('charset', $config)) { + $config['charset'] = null; + } + $mail = new $mailClass($config['charset']); + if (!$mail instanceof Zend_Mail) { + throw new Zend_Log_Exception($mail . 'must extend Zend_Mail'); + } + + if (isset($config['subject'])) { + $mail->setSubject($config['subject']); + } + + $headerAddresses = array_intersect_key($config, self::$_methodMapHeaders); + if (count($headerAddresses)) { + foreach ($headerAddresses as $header => $address) { + $method = self::$_methodMapHeaders[$header]; + if (is_array($address) && isset($address['name']) + && !is_numeric($address['name']) + ) { + $params = array( + $address['email'], + $address['name'] + ); + } else if (is_array($address) && isset($address['email'])) { + $params = $address['email']; + } else { + $params = array($address); + } + call_user_func_array(array($mail, $method), $params); + } + } + + return $mail; + } + + /** + * Construct a Zend_Layout instance based on a configuration array + * + * @param array $config + * @return Zend_Layout + */ + protected function _constructLayoutFromConfig(array $config) + { + $config = array_merge(array( + 'layout' => 'Zend_Layout', + 'layoutOptions' => null + ), $config); + + $layoutClass = $config['layout']; + $layout = new $layoutClass($config['layoutOptions']); + if (!$layout instanceof Zend_Layout) { + throw new Zend_Log_Exception($layout . 'must extend Zend_Layout'); + } + + return $layout; } /** Index: tests/Zend/Log/Writer/MailTest.php =================================================================== --- tests/Zend/Log/Writer/MailTest.php (revision 22824) +++ tests/Zend/Log/Writer/MailTest.php (working copy) @@ -59,6 +59,13 @@ class Zend_Log_Writer_MailTest extends PHPUnit_Framework_TestCase { /** + * Mock Transport for Zend_Mail + * + * @var Zend_Mail_Transport_Abstract + */ + protected $_transport; + + /** * Runs the test methods of this class. * * @return void @@ -70,6 +77,20 @@ $result = PHPUnit_TextUI_TestRunner::run($suite); } + protected function setUp() + { + $this->_transport = $this->getMockForAbstractClass( + 'Zend_Mail_Transport_Abstract', + array() + ); + Zend_Mail::setDefaultTransport($this->_transport); + } + + protected function tearDown() + { + Zend_Mail::clearDefaultTransport(); + } + /** * Tests normal logging, but with multiple messages for a level. * @@ -287,6 +308,162 @@ } /** + * @group ZF-9990 + */ + public function testFactory() + { + $config = array( + 'from' => array( + 'email' => 'log@test.framework.zend.com' + ), + 'to' => 'admin@domain.com', + 'subject' => '[error] exceptions on my application' + ); + + $writer = Zend_Log_Writer_Mail::factory($config); + $this->assertType('Zend_Log_Writer_Mail', $writer); + + $writer->write($this->_getEvent()); + $writer->shutdown(); + + $this->assertEquals('admin@domain.com', $this->_transport->recipients); + $this->assertContains('an info message', $this->_transport->body); + $this->assertContains('From: log@test.framework.zend.com', $this->_transport->header); + $this->assertContains('To: admin@domain.com', $this->_transport->header); + $this->assertContains('Subject: [error] exceptions on my application', $this->_transport->header); + } + + /** + * @group ZF-9990 + */ + public function testFactoryShouldSetSubjectPrependText() + { + $config = array( + 'subjectPrependText' => '[error] exceptions on my application' + ); + + $writer = Zend_Log_Writer_Mail::factory($config); + $writer->write($this->_getEvent()); + $writer->shutdown(); + + $this->assertContains('Subject: [error] exceptions on my application (INFO=1)', $this->_transport->header); + } + + /** + * @group ZF-9990 + */ + public function testFactoryShouldAcceptCustomMailClass() + { + $this->getMock('Zend_Mail', array(), array(), 'Zend_Stub_Mail_Custom'); + $config = array( + 'class' => 'Zend_Stub_Mail_Custom' + ); + + $writer = Zend_Log_Writer_Mail::factory($config); + $this->assertType('Zend_Log_Writer_Mail', $writer); + } + + /** + * @group ZF-9990 + */ + public function testFactoryShouldSetCharsetForMail() + { + $config = array( + 'charset' => 'UTF-8' + ); + + $writer = Zend_Log_Writer_Mail::factory($config); + $writer->write($this->_getEvent()); + $writer->shutdown(); + + $this->assertContains('Content-Type: text/plain; charset=UTF-8', $this->_transport->header); + } + + /** + * @group ZF-9990 + */ + public function testFactoryShouldAllowToSetMultipleRecipientsInArray() + { + $config = array( + 'to' => array( + 'John Doe' => 'admin1@domain.com', + 'admin2@domain.com' + ), + 'cc' => array( + 'bug@domain.com', + 'project' => 'projectname@domain.com' + ) + ); + + $writer = Zend_Log_Writer_Mail::factory($config); + $writer->write($this->_getEvent()); + $writer->shutdown(); + + $this->assertContains('admin1@domain.com', $this->_transport->recipients); + $this->assertContains('admin2@domain.com', $this->_transport->recipients); + $this->assertContains('bug@domain.com', $this->_transport->recipients); + $this->assertContains('projectname@domain.com', $this->_transport->recipients); + $this->assertContains('To: John Doe ', $this->_transport->header); + $this->assertContains('admin2@domain.com', $this->_transport->header); + $this->assertContains('Cc: bug@domain.com', $this->_transport->header); + $this->assertContains('project ', $this->_transport->header); + } + + /** + * @group ZF-9990 + */ + public function testFactoryWithLayout() + { + $config = array( + 'layoutOptions' => array( + 'layoutPath' => dirname(__FILE__) . '/_files' + ) + ); + + $writer = Zend_Log_Writer_Mail::factory($config); + $writer->write($this->_getEvent()); + $writer->shutdown(); + + $this->assertFalse(empty($this->_transport->boundary)); + $this->assertContains('Content-Type: multipart/', $this->_transport->header); + $this->assertContains('boundary=', $this->_transport->header); + $this->assertContains('Content-Type: text/plain', $this->_transport->body); + $this->assertContains('Content-Type: text/html', $this->_transport->body); + $this->assertContains($this->_transport->boundary, $this->_transport->body); + $this->assertEquals(2, substr_count($this->_transport->body, 'an info message')); + } + + /** + * @group ZF-9990 + */ + public function testFactoryShouldSetLayoutFormatter() + { + $config = array( + 'layoutOptions' => array( + 'layoutPath' => '/path/to/layout/scripts' + ), + 'layoutFormatter' => 'Zend_Log_Formatter_Simple' + ); + + $writer = Zend_Log_Writer_Mail::factory($config); + $this->assertType('Zend_Log_Formatter_Simple', $writer->getLayoutFormatter()); + } + + /** + * @group ZF-9990 + */ + public function testFactoryWithCustomLayoutClass() + { + $this->getMock('Zend_Layout', null, array(), 'Zend_Stub_Layout_Custom'); + $config = array( + 'layout' => 'Zend_Stub_Layout_Custom' + ); + + $writer = Zend_Log_Writer_Mail::factory($config); + $this->assertType('Zend_Log_Writer_Mail', $writer); + } + + /** * Returns an array of the Zend_Mail mock object, Zend_Log_Writer_Mail * object, and Zend_Log objects. * @@ -324,9 +501,24 @@ return array($mail, $writer, $log, $layout); } + + /** + * Returns a sample of an event + * + * @return array + */ + protected function _getEvent() + { + return array( + 'timestamp' => date('c'), + 'message' => 'an info message', + 'priority' => 6, + 'priorityName' => 'INFO' + ); + } } // Call Zend_Log_Writer_MailTest::main() if this source file is executed directly. if (PHPUnit_MAIN_METHOD == "Zend_Log_Writer_MailTest::main") { Zend_Log_Writer_MailTest::main(); -} +} \ No newline at end of file