Author: Alexandru Stanoi
Date: 2007-02-28 13:42:42 +0100 (Wed, 28 Feb 2007)
New Revision: 4696

Log:
- Implemented feature request #8485: added the ezcMailStorageSet which wraps
  around another set and provides saving of mail sources.

Added:
   trunk/Mail/src/transports/storage/
   trunk/Mail/src/transports/storage/storage_set.php
   trunk/Mail/tests/transports/transport_storage_test.php
Modified:
   trunk/Mail/ChangeLog
   trunk/Mail/src/mail_autoload.php
   trunk/Mail/src/transports/file/file_set.php
   trunk/Mail/src/transports/mbox/mbox_set.php
   trunk/Mail/src/transports/pop3/pop3_set.php
   trunk/Mail/src/transports/variable/var_set.php
   trunk/Mail/tests/suite.php

Modified: trunk/Mail/ChangeLog
===================================================================
--- trunk/Mail/ChangeLog        2007-02-28 08:25:07 UTC (rev 4695)
+++ trunk/Mail/ChangeLog        2007-02-28 12:42:42 UTC (rev 4696)
@@ -26,8 +26,10 @@
   Based on a patch from Mikko Koppanen.
 - Implemented feature request #10091: added SSL/TLS support for the SMTP
   transport. Based on a patch from Christian Michel. 
+- Implemented feature request #8485: added the ezcMailStorageSet which wraps
+  around another set and provides saving of mail sources.
 
-       
+
 1.2.1 - [RELEASEDATE]
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 

Modified: trunk/Mail/src/mail_autoload.php
===================================================================
--- trunk/Mail/src/mail_autoload.php    2007-02-28 08:25:07 UTC (rev 4695)
+++ trunk/Mail/src/mail_autoload.php    2007-02-28 12:42:42 UTC (rev 4696)
@@ -44,6 +44,7 @@
     'ezcMailMboxSet'                => 'Mail/transports/mbox/mbox_set.php',
     'ezcMailFileSet'                => 'Mail/transports/file/file_set.php',
     'ezcMailVariableSet'            => 'Mail/transports/variable/var_set.php',
+    'ezcMailStorageSet'             => 
'Mail/transports/storage/storage_set.php',
 
     'ezcMailException'              => 'Mail/exceptions/mail_exception.php',
     'ezcMailTransportException'     => 
'Mail/exceptions/transport_exception.php',

Modified: trunk/Mail/src/transports/file/file_set.php
===================================================================
--- trunk/Mail/src/transports/file/file_set.php 2007-02-28 08:25:07 UTC (rev 
4695)
+++ trunk/Mail/src/transports/file/file_set.php 2007-02-28 12:42:42 UTC (rev 
4696)
@@ -45,6 +45,16 @@
     private $files = array();
 
     /**
+     * This variable is true if there is more data in the mail that is being 
fetched.
+     *
+     * It is false if there is no mail being fetched currently or if all the 
data of the current mail
+     * has been fetched.
+     *
+     * @var bool
+     */
+    private $hasMoreMailData = false;
+
+    /**
      * Constructs a new set that servers the files specified by $files.
      *
      * The set will start on the first file in the the array.
@@ -55,8 +65,7 @@
     {
         $this->files = $files;
         reset( $this->files );
-
-        $this->openFile( true );
+        $this->hasMoreMailData = false;
     }
 
     /**
@@ -80,7 +89,7 @@
      */
     public function hasData()
     {
-        return count( $this->files );
+        return ( count( $this->files ) >= 1 ) && ( filesize( $this->files[0] ) 
> 0 );
     }
 
     /**
@@ -93,6 +102,10 @@
      */
     public function getNextLine()
     {
+        if ( $this->hasMoreMailData === false )
+        {
+            $this->nextMail();
+        }
         // finished?
         if ( $this->fp == null || feof( $this->fp ) )
         {
@@ -122,6 +135,11 @@
      */
     public function nextMail()
     {
+        if ( $this->hasMoreMailData === false )
+        {
+            $this->hasMoreMailData = true;
+            return $this->openFile( true );
+        }
         return $this->openFile();
     }
 

Modified: trunk/Mail/src/transports/mbox/mbox_set.php
===================================================================
--- trunk/Mail/src/transports/mbox/mbox_set.php 2007-02-28 08:25:07 UTC (rev 
4695)
+++ trunk/Mail/src/transports/mbox/mbox_set.php 2007-02-28 12:42:42 UTC (rev 
4696)
@@ -79,7 +79,6 @@
         $this->hasMoreMailData = true;
         $this->messagePositions = $messages;
         $this->currentMessagePosition = 0;
-        $this->nextMail();
     }
 
     /**
@@ -103,6 +102,10 @@
      */
     public function getNextLine()
     {
+        if ( $this->currentMessagePosition === 0 )
+        {
+            $this->nextMail();
+        }
         if ( $this->hasMoreMailData )
         {
             $data = fgets( $this->fh );
@@ -124,7 +127,7 @@
      */
     public function hasData()
     {
-        return $this->hasMoreMailData;
+        return ( $this->hasMoreMailData === true && count( 
$this->messagePositions ) > 0 );
     }
 
     /**
@@ -148,5 +151,15 @@
 
         return true;
     }
+
+    /**
+     * Returns message numbers for current set.
+     *
+     * @return array(int=>int)
+     */
+    public function getMessageNumbers()
+    {
+        return array_keys( $this->messagePositions );
+    }
 }
 ?>

Modified: trunk/Mail/src/transports/pop3/pop3_set.php
===================================================================
--- trunk/Mail/src/transports/pop3/pop3_set.php 2007-02-28 08:25:07 UTC (rev 
4695)
+++ trunk/Mail/src/transports/pop3/pop3_set.php 2007-02-28 12:42:42 UTC (rev 
4696)
@@ -52,6 +52,8 @@
 
     /**
      * Holds if mail should be deleted from the server after retrieval.
+     *
+     * @var bool
      */
     private $deleteFromServer = false;
 
@@ -75,7 +77,6 @@
         $this->connection = $connection;
         $this->messages = $messages;
         $this->deleteFromServer = $deleteFromServer;
-        $this->nextMail();
     }
 
     /**
@@ -98,6 +99,10 @@
      */
     public function getNextLine()
     {
+        if ( $this->currentMessage === null )
+        {
+            $this->nextMail();
+        }
         if ( $this->hasMoreMailData )
         {
             $data = $this->connection->getLine();
@@ -110,7 +115,6 @@
                     $this->connection->sendData( "DELE 
{$this->currentMessage}" );
                     $response = $this->connection->getLine(); // ignore 
response
                 }
-
                 return null;
             }
             return $data;
@@ -137,8 +141,7 @@
         {
             $this->currentMessage = next( $this->messages );
         }
-
-        if ( is_integer( $this->currentMessage ) )
+        if ( $this->currentMessage !== false )
         {
             $this->connection->sendData( "RETR {$this->currentMessage}" );
             $response = $this->connection->getLine();

Added: trunk/Mail/src/transports/storage/storage_set.php
===================================================================
--- trunk/Mail/src/transports/storage/storage_set.php   2007-02-28 08:25:07 UTC 
(rev 4695)
+++ trunk/Mail/src/transports/storage/storage_set.php   2007-02-28 12:42:42 UTC 
(rev 4696)
@@ -0,0 +1,223 @@
+<?php
+/**
+ * File containing the ezcMailStorageSet class
+ *
+ * @package Mail
+ * @version //autogen//
+ * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ */
+
+/**
+ * ezcMailStorageSet is a wrapper around other mail sets and provides saving of
+ * mail sources to files.
+ *
+ * Example:
+ *
+ * <code>
+ * // create a new POP3 transport object and a mail parser object
+ * $transport = new ezcMailPop3Transport( "server" );
+ * $transport->authenticate( "username", "password" );
+ * $parser = new ezcMailParser();
+ *
+ * // wrap around the set returned by fetchAll()
+ * // and specify that the sources are to be saved in the folder /tmp/cache
+ * $set = new ezcMailStorageSet( $transport->fetchAll(), '/tmp/cache' );
+ *
+ * // parse the storage set
+ * $mail = $parser->parseMail( $set );
+ *
+ * // get the filenames of the saved mails in the set
+ * // this must be saved somewhere so it can be used on a subsequent request
+ * $files = $set->getSourceFiles();
+ *
+ * // get the source of a the 4th saved mail
+ * // this can be on a subsequent request if the $files array was saved from
+ * // a previous request
+ * $source = file_get_contents( $files[3] );
+ * </code>
+ *
+ * @package Mail
+ * @version //autogen//
+ */
+class ezcMailStorageSet implements ezcMailParserSet
+{
+    /**
+     * Holds the pointer to the current file which holds the mail source.
+     *
+     * @var filepointer
+     */
+    private $writer = null;
+
+    /**
+     * Holds the temporary file name where contents are being initially written
+     * (until set is parsed and Message-ID is extracted).
+     *
+     * @var string
+     */
+    private $file = null;
+
+    /**
+     * Holds the path where the files are written (specified in the 
constructor).
+     *
+     * @var string
+     */
+    private $path = null;
+
+    /**
+     * Holds the Message-ID of the current message, used to rename the mail 
source file.
+     *
+     * @var string
+     */
+    private $id = null;
+
+    /**
+     * This variable is true if there is more data in the mail that is being 
fetched.
+     *
+     * @var bool
+     */
+    private $hasMoreMailData = false;
+
+    /**
+     * Holds the location where to store the message sources.
+     *
+     * @var string
+     */
+    private $location;
+
+    /**
+     * Holds the filenames holding the sources of the mails in this set.
+     *
+     * @var array(string)
+     */
+    private $files = null;
+
+    /**
+     * Constructs a new storage set around the provided set.
+     *
+     * $location specifies where to save the message sources. This directory 
MUST
+     * exist and must be writable.
+     *
+     * @param ezcMailParserSet $set
+     * @param array(string=>mixed) $options
+     */
+    public function __construct( ezcMailParserSet $set, $location )
+    {
+        $this->set = $set;
+        $this->location = $location;
+        $this->path = rtrim( $this->location, DIRECTORY_SEPARATOR ) . 
DIRECTORY_SEPARATOR;
+        $this->hasMoreMailData = false;
+    }
+
+    /**
+     * Destructs the set.
+     *
+     * Closes any open files.
+     */
+    public function __destruct()
+    {
+        if ( $this->writer !== null )
+        {
+            fclose( $this->writer );
+            $this->writer = null;
+        }
+    }
+
+    /**
+     * Returns one line of data from the current mail in the set.
+     *
+     * Null is returned if there is no current mail in the set or
+     * the end of the mail is reached,
+     *
+     * It also writes the line of data to the current file. If the line 
contains
+     * a Message-ID header then the value in the header will be used to rename 
the
+     * file.
+     *
+     * @return string
+     */
+    public function getNextLine()
+    {
+        if ( $this->hasMoreMailData === false )
+        {
+            $this->nextMail();
+            $this->hasMoreMailData = true;
+        }
+        $line = $this->set->getNextLine();
+        if ( $this->id === null && stripos( $line, 'message-id' ) !== false )
+        {
+            // Temporary value in case the Message-ID cannot be extracted from 
$line
+            $this->id = $this->file;
+            preg_match_all( "/^([\w-_]*): (.*)/", $line, $matches, 
PREG_SET_ORDER );
+            if ( count( $matches ) > 0 )
+            {
+                $this->id = trim( trim( $matches[0][2] ), '<>' );
+            }
+        }
+        fputs( $this->writer, $line );
+        return $line;
+    }
+
+    /**
+     * Moves the set to the next mail and returns true upon success.
+     *
+     * False is returned if there are no more mail in the set.
+     *
+     * @return bool
+     */
+    public function nextMail()
+    {
+        if ( $this->writer !== null )
+        {
+            fclose( $this->writer );
+            if ( $this->id !== null )
+            {
+                rename( $this->path . $this->file, $this->path . $this->id );
+                $this->files[] = $this->path . $this->id;
+            }
+            else
+            {
+                $this->files[] = $this->path . $this->file;
+            }
+            $this->writer = null;
+        }
+        $this->id = null;
+        $mail = $this->set->nextMail();
+        if ( $mail === true || $this->hasMoreMailData === false )
+        {
+            // Temporary file name until message is parsed and Message-ID is 
extracted.
+            // It could remain the same if the mail doesn't contain a 
Message-ID header
+            $this->file = getmypid() . '.' . time();
+            $writer = fopen( $this->path . $this->file, 'w' );
+            if ( $writer !== false )
+            {
+                $this->writer = $writer;
+            }
+            return $mail;
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether the set has mails.
+     *
+     * @return bool
+     */
+    public function hasData()
+    {
+        return $this->set->hasData();
+    }
+
+    /**
+     * Returns an array of the filenames holding the sources of the mails in 
this set.
+     *
+     * The format of the returned array is:
+     * array( 0 => 'location/filename1', 1 => 'location/filename2',...)
+     *
+     * @return array(string)
+     */
+    public function getSourceFiles()
+    {
+        return $this->files;
+    }
+}
+?>


Property changes on: trunk/Mail/src/transports/storage/storage_set.php
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/Mail/src/transports/variable/var_set.php
===================================================================
--- trunk/Mail/src/transports/variable/var_set.php      2007-02-28 08:25:07 UTC 
(rev 4695)
+++ trunk/Mail/src/transports/variable/var_set.php      2007-02-28 12:42:42 UTC 
(rev 4696)
@@ -88,7 +88,7 @@
      */
     public function hasData()
     {
-        return true;
+        return ( count( $this->mail ) > 1 );
     }
 }
 ?>

Modified: trunk/Mail/tests/suite.php
===================================================================
--- trunk/Mail/tests/suite.php  2007-02-28 08:25:07 UTC (rev 4695)
+++ trunk/Mail/tests/suite.php  2007-02-28 12:42:42 UTC (rev 4696)
@@ -33,6 +33,7 @@
 require_once( "transports/transport_mbox_test.php" );
 require_once( "transports/transport_file_test.php" );
 require_once( "transports/transport_imap_test.php" );
+require_once( "transports/transport_storage_test.php" );
 require_once( "transports/transport_variable_test.php" );
 require_once( "tutorial_examples.php" );
 require_once( "parser/parser_test.php" );
@@ -75,6 +76,7 @@
         $this->addTest( ezcMailTransportImapTest::suite() );
         $this->addTest( ezcMailTransportMboxTest::suite() );
         $this->addTest( ezcMailTransportFileTest::suite() );
+        $this->addTest( ezcMailTransportStorageTest::suite() );
         $this->addTest( ezcMailTransportVariableTest::suite() );
         $this->addTest( ezcMailTutorialExamples::suite() );
         $this->addTest( ezcMailParserTest::suite() );

Added: trunk/Mail/tests/transports/transport_storage_test.php
===================================================================
--- trunk/Mail/tests/transports/transport_storage_test.php      2007-02-28 
08:25:07 UTC (rev 4695)
+++ trunk/Mail/tests/transports/transport_storage_test.php      2007-02-28 
12:42:42 UTC (rev 4696)
@@ -0,0 +1,236 @@
+<?php
+/**
+ * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ * @version //autogentag//
+ * @filesource
+ * @package Mail
+ * @subpackage Tests
+ */
+
+/**
+ * @package Mail
+ * @subpackage Tests
+ */
+class ezcMailTransportStorageTest extends ezcTestCase
+{
+    public function testImapMessageSource()
+    {
+        $transport = new ezcMailImapTransport( "dolly.ez.no" );
+        $transport->authenticate( "ezcomponents", "ezcomponents" );
+        $transport->selectMailbox( "Inbox" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchByMessageNr( 1 ), 
$this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 1542, strlen( $source ) );
+    }
+
+    public function testImapMessageSourceFetchAll()
+    {
+        $transport = new ezcMailImapTransport( "dolly.ez.no" );
+        $transport->authenticate( "ezcomponents", "ezcomponents" );
+        $transport->selectMailbox( "Inbox" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 1542, strlen( $source ) );
+    }
+
+    public function testImapMessageSourceEmptySet()
+    {
+        $transport = new ezcMailImapTransport( "dolly.ez.no" );
+        $transport->authenticate( "ezcomponents", "ezcomponents" );
+        $transport->createMailbox( "Guybrush" );
+        $transport->selectMailbox( "Guybrush" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $this->assertEquals( array(), $mail );
+        $transport->selectMailbox( "Inbox" );
+        $transport->deleteMailbox( "Guybrush" );
+    }
+
+    public function testPop3MessageSource()
+    {
+        $transport = new ezcMailPop3Transport( "dolly.ez.no" );
+        $transport->authenticate( "ezcomponents", "ezcomponents" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchByMessageNr( 1 ), 
$this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 1542, strlen( $source ) );
+    }
+
+    public function testPop3MessageSourceFetchAll()
+    {
+        $transport = new ezcMailPop3Transport( "dolly.ez.no" );
+        $transport->authenticate( "ezcomponents", "ezcomponents" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 1542, strlen( $source ) );
+    }
+
+    public function testMboxMessageSource()
+    {
+        $transport = new ezcMailMboxTransport( dirname( __FILE__ ) . 
"/data/testlimit-mbox" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchByMessageNr( 1 ), 
$this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 2609, strlen( $source ) );
+    }
+
+    public function testMboxMessageSourceFetchAll()
+    {
+        $transport = new ezcMailMboxTransport( dirname( __FILE__ ) . 
"/data/testlimit-mbox" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 2925, strlen( $source ) );
+    }
+
+    public function testMboxMessageEmpty()
+    {
+        $transport = new ezcMailMboxTransport( dirname( __FILE__ ) . 
"/data/empty.mbox" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $this->assertEquals( 0, count( $mail ) );
+    }
+
+    public function testVariableMessageSource()
+    {
+        $parser = new ezcMailParser();
+        $message = file_get_contents( dirname( __FILE__ ) . 
"/data/test-variable" );
+
+        $set = new ezcMailStorageSet( new ezcMailVariableSet( $message ), 
$this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 1445, strlen( $source ) );
+    }
+
+    public function testVariableMessageSourceEmpty()
+    {
+        $parser = new ezcMailParser();
+        $message = "";
+
+        $set = new ezcMailStorageSet( new ezcMailVariableSet( $message ), 
$this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $this->assertEquals( array(), $mail );
+    }
+
+    public function testFileMessageSource()
+    {
+        $parser = new ezcMailParser();
+        $messages = array( dirname( __FILE__ ) . "/data/test-variable" );
+
+        $set = new ezcMailStorageSet( new ezcMailFileSet( $messages ), 
$this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 1444, strlen( $source ) );
+    }
+
+    public function testFileMessageSourceMultiple()
+    {
+        $parser = new ezcMailParser();
+        $messages = array( dirname( __FILE__ ) . "/data/test-variable", 
dirname( __FILE__ ) . "/data/test-variable" );
+
+        $set = new ezcMailStorageSet( new ezcMailFileSet( $messages ), 
$this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+
+        $source = file_get_contents( $files[0] );
+        $this->assertEquals( 1444, strlen( $source ) );
+        $source = file_get_contents( $files[1] );
+        $this->assertEquals( 1444, strlen( $source ) );
+    }
+
+    public function testFileMessageSourceEmpty()
+    {
+        $parser = new ezcMailParser();
+        $fileName = $this->tempDir . "/empty-message";
+        $fileHandle = fopen( $fileName, "w" );
+        fwrite( $fileHandle, "" );
+        fclose( $fileHandle );
+        $messages = array( $fileName );
+
+        $set = new ezcMailStorageSet( new ezcMailFileSet( $messages ), 
$this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $this->assertEquals( array(), $mail );
+    }
+
+    public function testGetSourceFileNames()
+    {
+        $transport = new ezcMailImapTransport( "dolly.ez.no" );
+        $transport->authenticate( "ezcomponents", "ezcomponents" );
+        $transport->selectMailbox( "Inbox" );
+        $parser = new ezcMailParser();
+
+        $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir );
+        $mail = $parser->parseMail( $set );
+        $files = $set->getSourceFiles();
+        $expected = array( "[EMAIL PROTECTED]",
+                           "[EMAIL PROTECTED]",
+                           "[EMAIL PROTECTED]",
+                           "[EMAIL PROTECTED]" );
+        for ( $i = 0; $i < count( $files ); $i++ )
+        {
+            $this->assertEquals( $expected[$i], basename( $files[$i] ) );
+        }
+    }
+
+    public function setUp()
+    {
+        $this->tempDir = $this->createTempDir( 'ezcMailTransportStorageTest' );
+    }
+
+    public function tearDown()
+    {
+        $this->removeTempDir();
+
+        $transport = new ezcMailImapTransport( "dolly.ez.no" );
+        $transport->authenticate( "ezcomponents", "ezcomponents" );
+        try
+        {
+            $transport->deleteMailbox( "Guybrush" );
+        }
+        catch ( ezcMailTransportException $e )
+        {
+        }
+    }
+
+    public static function suite()
+    {
+        return new PHPUnit_Framework_TestSuite( "ezcMailTransportStorageTest" 
);
+    }
+}
+?>


Property changes on: trunk/Mail/tests/transports/transport_storage_test.php
___________________________________________________________________
Name: svn:eol-style
   + native

-- 
svn-components mailing list
svn-components@lists.ez.no
http://lists.ez.no/mailman/listinfo/svn-components

Reply via email to