From a298d68b4edcaf4824018f55e22e7f2ca11b45e3 Mon Sep 17 00:00:00 2001 From: Leander Date: Mon, 26 Nov 2012 00:25:07 +0100 Subject: [PATCH 1/8] Initial Doctrine Container WIP --- composer.json | 3 +- src/PEAR2/Mail/Queue/Container/doctrine2.php | 235 ++++++++++++++++++- tests/Mail/Queue/DoctrineContainerTest.php | 54 +++-- tests/Mail/QueueDoctrineAbstract.php | 101 ++++++++ tests/TestInit.php | 1 + 5 files changed, 365 insertions(+), 29 deletions(-) create mode 100644 tests/Mail/QueueDoctrineAbstract.php diff --git a/composer.json b/composer.json index 31123bb..4dcee33 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ "require": { "pear-pear/MDB2": "2.5.0b5", "pear-pear/Mail": "*", - "pear-pear/Mail_Mime": "*" + "pear-pear/Mail_Mime": "*", + "doctrine/orm": "2.4.x-dev" } } diff --git a/src/PEAR2/Mail/Queue/Container/doctrine2.php b/src/PEAR2/Mail/Queue/Container/doctrine2.php index c12cd7a..f2b1c34 100644 --- a/src/PEAR2/Mail/Queue/Container/doctrine2.php +++ b/src/PEAR2/Mail/Queue/Container/doctrine2.php @@ -1,13 +1,244 @@ config = $options['doctrine']; + + if (isset($options['em'])) { + $this->em = $options['em']; + } else { + $this->em = $this->getEntityManager(); + } + + $this->setOption(); + } + + /** + * Setup Doctrine Class Loaders & EntityManager + * + * return void + */ + protected function init() + { + + $config = new Configuration(); + $cache = new $this->config['cacheImplementation']; + $entityFolder = __DIR__ . '/../Entity'; + $driverImpl = $config->newDefaultAnnotationDriver($entityFolder); + + AnnotationReader::addGlobalIgnoredName('package_version'); + $annotationReader = new AnnotationReader; + $cachedAnnotationReader = new \Doctrine\Common\Annotations\CachedReader( + $annotationReader, // use reader + $cache // and a cache driver + ); + + $annotationDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver( + $cachedAnnotationReader, // our cached annotation reader + array($entityFolder) // paths to look in + ); + + + $config->setMetadataDriverImpl($annotationDriver); + $config->setMetadataCacheImpl($cache); + $config->setQueryCacheImpl($cache); + $config->setProxyDir(__DIR__ . '/../Proxy'); + $config->setProxyNamespace($this->config['proxy']['namespace']); + $config->setAutoGenerateProxyClasses($this->config['autoGenerateProxyClasses']); + + $connectionConfig = $this->config['connection']; + + $this->em = EntityManager::create( + $connectionConfig, + $config + ); + + PersistentObject::setObjectManager($this->em); + return; + } + + /** + * Get the Doctrine EntityManager + * + * @return Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + if (isset($this->em)) { + return $this->em; + } + $this->init(); + return $this->em; + } + + /** + * Get the Doctrine EntityManager + * + */ + public function setEntityManager($em) + { + $this->em = $em; + return $this; + } + + protected function _preload() + { + // TODO: Implement _preload() method. + } + + /** + * Put new mail in queue. + * + * Mail_Queue_Container::put() + * + * @param string $time_to_send When mail have to be send + * @param integer $id_user Sender id + * @param string $ip Sender ip + * @param string $from Sender e-mail + * @param string $to Reciepient e-mail + * @param string $hdrs Mail headers (in RFC) + * @param string $body Mail body (in RFC) + * + * @return bool True on success + **/ + function put($time_to_send, $id_user, $ip, $from, $to, $hdrs, $body, $delete_after_send) + { + $queueRecord = new Mail(); + + $queueRecord + ->__set('createTime', new \DateTime()) + ->__set('timeToSend', new \DateTime($time_to_send)) + ->__set('idUser', $id_user) + ->__set('ip', $ip) + ->__set('sender', $from) + ->__set('recipient', $to) + ->__set('headers', $hdrs) + ->__set('body', $body) + ->__set('deleteAfterSend', ($delete_after_send ? 1 : 0)); + + $this->em->persist($queueRecord); + $this->em->flush(); + + return $queueRecord->__get('id'); + + // TODO: Implement put() method. + } + + /** + * Check how many times mail was sent. + * + * @param Body $mail object + * + * @return mixed Integer or false if error. + */ + function countSend(Body $mail) + { + // TODO: Implement countSend() method. + } + + /** + * Set mail as already sent. + * + * @param Body $mail object + * + * @return bool + */ + function setAsSent(Body $mail) + { + // TODO: Implement setAsSent() method. + } + + /** + * Return mail by id $id (bypass mail_queue) + * + * @param integer $id Mail ID + * + * @return mixed Mail object or false on error. + */ + function getMailById($id) + { + $repo = $this->em->getRepository('PEAR2\Mail\Queue\Entity\Mail'); + $mailRecord = $repo->find($id); + + if (NULL == $mailRecord) { + throw new Exception( + sprintf($this->errorMsg, $id, 'no message with id'), + Queue::ERROR_QUERY_FAILED + ); + } + + return new Body( + $mailRecord->getId(), + $mailRecord->getCreateTime(), + $mailRecord->getTimeToSend(), + $mailRecord->getTimeToSend(), + $mailRecord->getIdUser(), + $mailRecord->getIp(), + $mailRecord->getSender(), + $this->_isSerialized($mailRecord->getRecipient()) ? unserialize($mailRecord->getRecipient()) : $mailRecord->getRecipient(), + unserialize($mailRecord->getHeaders()), + unserialize($mailRecord->getBody()), + $mailRecord->getDeleteAfterSend(), + $mailRecord->getTrySent() + ); + } + + function getQueueCount() + { + // TODO: Implement getQueueCount() method. + } + + /** + * Remove from queue mail with $id identifier. + * + * @param integer $id Mail ID + * + * @return bool True on success ale false. + */ + function deleteMail($id) + { + // TODO: Implement deleteMail() method. + } + + } diff --git a/tests/Mail/Queue/DoctrineContainerTest.php b/tests/Mail/Queue/DoctrineContainerTest.php index 302b2a0..7c8e958 100644 --- a/tests/Mail/Queue/DoctrineContainerTest.php +++ b/tests/Mail/Queue/DoctrineContainerTest.php @@ -1,37 +1,39 @@ register(); - - $params = array( - 'dbname' => ':MEMORY:', - 'driver' => 'pdo_sqlite', - ); - - $this->dbal = DriverManager::getConnection($params, new Configuration); + parent::setUp(); } - public function testInit() + public function testContainerGet() { - $container_opts = array( - 'type' => 'doctrine', - 'dsn' => $this->dbal, - 'mail_table' => 'mail_queue', - ); + $time_to_send = 3600; + $id_user = 1; + $sender = 'testsuite@example.org'; + $recipient = 'testcase@example.org'; + $headers = array('X-TestSuite' => 1); + $body = 'Lorem ipsum'; + + $mailId = $this->queue->put($sender, $recipient, $headers, $body, 0, true, $id_user); + if (!is_numeric($mailId)) { + $this->fail("Could not save email."); + return; + } + + $message = $this->queue->container->getMailById($mailId); + $this->assertTrue(($message instanceof PEAR2\Mail\Queue\Body)); + + $this->assertEquals($mailId, $message->getId()); + $this->assertEquals($id_user, $message->getIdUser()); + $this->assertEquals('', $message->getIp()); + $this->assertEquals($sender, $message->getSender()); + $this->assertEquals($recipient, $message->getRecipient()); + $this->assertEquals($headers, $message->getHeaders()); + $this->assertEquals($body, $message->getBody()); + $this->assertTrue($message->isDeleteAfterSend()); } + } diff --git a/tests/Mail/QueueDoctrineAbstract.php b/tests/Mail/QueueDoctrineAbstract.php new file mode 100644 index 0000000..16c90a8 --- /dev/null +++ b/tests/Mail/QueueDoctrineAbstract.php @@ -0,0 +1,101 @@ + 'Doctrine\Common\Cache\ArrayCache', + 'connection' => array( + 'driver' => 'pdo_sqlite', + 'dbname' => '', + 'user' => '', + 'host' => '', + 'password' => '', + 'memory' => true + ), + 'autoGenerateProxyClasses' => 1, + 'proxy' => array('namespace' => 'Proxy') + ); + + $doctrineDriver = new PEAR2\Mail\Queue\Container\doctrine2(array('doctrine' => $doctrineConfig)); + + $this->em = $doctrineDriver->getEntityManager(); + + $this->initDoctrineTestSetup(); + + + $container_opts = array( + 'type' => 'doctrine2', + 'doctrine' => $doctrineConfig, + 'em' => $this->em + ); + + /** + * @see Mail_mock + */ + $mail_opts = array('driver' => 'mock'); + + $this->queue = new Queue($container_opts, $mail_opts); + if ($this->queue->hasErrors()) { + $errors = $this->queue->getErrors(); + $fail = "The following errors occurred:\n"; + foreach ($errors as $error) { + $fail .= $error->getMessage() . "\n"; + } + $this->fail($fail); + } + } + + + protected function initDoctrineTestSetup() + { + + $tool = new \Doctrine\ORM\Tools\SchemaTool($this->em); + $classes = array( + $this->em->getClassMetadata('PEAR2\Mail\Queue\Entity\Mail'), + ); + + $tool->createSchema($classes); + } + + /** + * Remove the table/artifacts. + * + * @return void + * @see self::setUpDatabase() + */ + public function tearDown() + { + $tool = new \Doctrine\ORM\Tools\SchemaTool($this->em); + $tool->dropDatabase(); + unset($this->em); + parent::tearDown(); + + + //$this->queue->container->db->disconnect(); + unset($this->queue); + } + +} diff --git a/tests/TestInit.php b/tests/TestInit.php index f5bc3c4..2283c02 100644 --- a/tests/TestInit.php +++ b/tests/TestInit.php @@ -7,6 +7,7 @@ exit(1); } +require_once __DIR__ . '/../vendor/autoload.php'; require_once 'MDB2.php'; class MailQueueTestInit From 30fea4c5dbb56d613c50d5bd7d54f80537dcaa56 Mon Sep 17 00:00:00 2001 From: Leander Date: Mon, 26 Nov 2012 00:55:53 +0100 Subject: [PATCH 2/8] CS polish --- src/PEAR2/Mail/Queue/Container/doctrine2.php | 129 +++++++++++++++---- 1 file changed, 107 insertions(+), 22 deletions(-) diff --git a/src/PEAR2/Mail/Queue/Container/doctrine2.php b/src/PEAR2/Mail/Queue/Container/doctrine2.php index f2b1c34..f4e2231 100644 --- a/src/PEAR2/Mail/Queue/Container/doctrine2.php +++ b/src/PEAR2/Mail/Queue/Container/doctrine2.php @@ -1,4 +1,51 @@ | + * +----------------------------------------------------------------------+ + * + * PHP Version 5.3 + * + * @category Mail + * @package Mail_Queue + * @author Leander Damme + * @license http://www.opensource.org/licenses/bsd-license.php The BSD License + * @link http://pear.php.net/package/Mail_Queue + */ + namespace PEAR2\Mail\Queue\Container; use PEAR2\Mail\Queue\Container; @@ -6,7 +53,6 @@ use PEAR2\Mail\Queue; use PEAR2\Mail\Queue\Body; use PEAR2\Mail\Queue\Entity\Mail; - use Doctrine\ORM\EntityManager; use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Common\Persistence\PersistentObject; @@ -14,13 +60,36 @@ use Doctrine\Common\Annotations\AnnotationReader; -class doctrine2 extends Container +/** + * Storage driver for fetching mail queue data with Doctrine2 + * + * This storage driver can use all databases which are supported + * by the DoctrineORM abstraction layer. + * + * @category Mail + * @package Mail_Queue + * @author Leander Damme + * @license http://www.opensource.org/licenses/bsd-license.php The BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/Mail_Queue + */ + +class Doctrine2 extends Container { + /** + * @var Doctrine\ORM\EntityManager + */ protected $em; + /** + * @var Entity Classname + */ protected $entity; + /** + * @var + */ protected $config; /** @@ -28,7 +97,7 @@ class doctrine2 extends Container * * Mail_Queue_Container_doctrine2() * - * @param array $options An associative array of connection option. + * @param array $options An associative array of connection option. * * @return hmmm */ @@ -56,7 +125,7 @@ public function __construct(array $options) /** * Setup Doctrine Class Loaders & EntityManager * - * return void + * @return void */ protected function init() { @@ -114,6 +183,9 @@ public function getEntityManager() /** * Get the Doctrine EntityManager * + * @param Doctrine\ORM\EntityManager $em EntityManager + * + * @return \PEAR2\Mail\Queue\Container\doctrine2 */ public function setEntityManager($em) { @@ -121,6 +193,12 @@ public function setEntityManager($em) return $this; } + /** + * Preload mail to queue. + * + * @return true + * @throws Exception + */ protected function _preload() { // TODO: Implement _preload() method. @@ -131,17 +209,18 @@ protected function _preload() * * Mail_Queue_Container::put() * - * @param string $time_to_send When mail have to be send - * @param integer $id_user Sender id - * @param string $ip Sender ip - * @param string $from Sender e-mail - * @param string $to Reciepient e-mail - * @param string $hdrs Mail headers (in RFC) - * @param string $body Mail body (in RFC) + * @param string $time_to_send When mail have to be send + * @param integer $id_user Sender id + * @param string $ip Sender ip + * @param string $from Sender e-mail + * @param string $to Reciepient e-mail + * @param string $hdrs Mail headers (in RFC) + * @param string $body Mail body (in RFC) + * @param bool $delete_after_send (not sure wether in RFC) * * @return bool True on success **/ - function put($time_to_send, $id_user, $ip, $from, $to, $hdrs, $body, $delete_after_send) + public function put($time_to_send, $id_user, $ip, $from, $to, $hdrs, $body, $delete_after_send) { $queueRecord = new Mail(); @@ -171,7 +250,7 @@ function put($time_to_send, $id_user, $ip, $from, $to, $hdrs, $body, $delete_aft * * @return mixed Integer or false if error. */ - function countSend(Body $mail) + public function countSend(Body $mail) { // TODO: Implement countSend() method. } @@ -183,24 +262,26 @@ function countSend(Body $mail) * * @return bool */ - function setAsSent(Body $mail) + public function setAsSent(Body $mail) { // TODO: Implement setAsSent() method. + return $this; + } /** * Return mail by id $id (bypass mail_queue) * - * @param integer $id Mail ID + * @param integer $id Mail ID * * @return mixed Mail object or false on error. */ - function getMailById($id) + public function getMailById($id) { $repo = $this->em->getRepository('PEAR2\Mail\Queue\Entity\Mail'); $mailRecord = $repo->find($id); - if (NULL == $mailRecord) { + if (null == $mailRecord) { throw new Exception( sprintf($this->errorMsg, $id, 'no message with id'), Queue::ERROR_QUERY_FAILED @@ -223,7 +304,13 @@ function getMailById($id) ); } - function getQueueCount() + /** + * Return the number of emails currently in the queue. + * + * @return int + * @throws Exception + */ + public function getQueueCount() { // TODO: Implement getQueueCount() method. } @@ -231,14 +318,12 @@ function getQueueCount() /** * Remove from queue mail with $id identifier. * - * @param integer $id Mail ID + * @param integer $id Mail ID * * @return bool True on success ale false. */ - function deleteMail($id) + public function deleteMail($id) { // TODO: Implement deleteMail() method. } - - } From 169710f44ffb38ba23c2a5f63328ca2bef2a667d Mon Sep 17 00:00:00 2001 From: Leander Date: Mon, 26 Nov 2012 00:58:48 +0100 Subject: [PATCH 3/8] added travis ci --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f792900 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: php + +php: + - 5.3 + - 5.4 + +before_script: + - wget http://getcomposer.org/composer.phar -O ./composer.phar + - chmod +x composer.phar + - ./composer.phar install --prefer-dist + - gem install colored -v=1.2 + +script: phpunit \ No newline at end of file From 17a055a32f911ea6495be02fbca76a2ac5f108c4 Mon Sep 17 00:00:00 2001 From: Leander Date: Mon, 26 Nov 2012 01:10:13 +0100 Subject: [PATCH 4/8] Mail/QueueItem Entity and Repo --- src/PEAR2/Mail/Queue/Entity/Mail.php | 241 ++++++++++++++++++ .../Entity/Repository/MailRepository.php | 12 + 2 files changed, 253 insertions(+) create mode 100644 src/PEAR2/Mail/Queue/Entity/Mail.php create mode 100644 src/PEAR2/Mail/Queue/Entity/Repository/MailRepository.php diff --git a/src/PEAR2/Mail/Queue/Entity/Mail.php b/src/PEAR2/Mail/Queue/Entity/Mail.php new file mode 100644 index 0000000..4c1fdeb --- /dev/null +++ b/src/PEAR2/Mail/Queue/Entity/Mail.php @@ -0,0 +1,241 @@ +$property; + } + + /** + * Magic setter to save protected properties. + * + * @param string $property '' + * @param mixed $value '' + * + * @return void + */ + public function __set($property, $value) + { + $this->$property = $value; + return $this; + } + + /** + * Convert the object to an array. + * + * @return array + */ + public function getArrayCopy() + { + return get_object_vars($this); + } + + + /** + * get time queue item was created + * + * @return \DateTime + */ + public function getCreateTime() + { + return $this->createTime; + } + + /** + * get ID + * + * @return mixed + */ + public function getId() + { + return $this->id; + } + + /** + * get User ID + * + * @return mixed + */ + public function getIdUser() + { + return $this->idUser; + } + + /** + * get IP + * + * @return mixed + */ + public function getIp() + { + return $this->ip; + } + + /** + * get recipient + * + * @return mixed + */ + public function getRecipient() + { + return $this->recipient; + } + + /** + * get sender + * + * @return mixed + */ + public function getSender() + { + return $this->sender; + } + + /** + * get time mail is scheduled for + * + * @return \DateTime + */ + public function getTimeToSend() + { + return $this->timeToSend; + } + + /** + * get time mail was sent + * + * @return \DateTime + */ + public function getSentTime() + { + return $this->sentTime; + } + + + /** + * get body + * + * @return mixed + */ + public function getBody() + { + return $this->body; + } + + /** + * get delete after send + * + * @return bool + */ + public function getDeleteAfterSend() + { + return (boolean)$this->deleteAfterSend; + } + + /** + * get headers + * + * @return mixed + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * get number of tries sending + * + * @return mixed + */ + public function getTrySent() + { + return $this->trySent; + } +} diff --git a/src/PEAR2/Mail/Queue/Entity/Repository/MailRepository.php b/src/PEAR2/Mail/Queue/Entity/Repository/MailRepository.php new file mode 100644 index 0000000..dd4eb06 --- /dev/null +++ b/src/PEAR2/Mail/Queue/Entity/Repository/MailRepository.php @@ -0,0 +1,12 @@ + Date: Wed, 28 Nov 2012 01:52:31 +0100 Subject: [PATCH 5/8] moar tests, implemented all container methods... --- README.md | 8 +- src/PEAR2/Mail/Queue/Container/doctrine2.php | 136 +++++++++++++-- src/PEAR2/Mail/Queue/Entity/Mail.php | 12 +- .../Entity/Repository/MailRepository.php | 35 ++++ tests/Mail/Queue/DoctrineContainerTest.php | 164 ++++++++++++++++++ tests/Mail/QueueDoctrineAbstract.php | 5 + 6 files changed, 346 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 2f2693b..59581a2 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,14 @@ The API is very similar except for: Until I get to PEAR2, just use composer. +## WIP + +topics/doctrine + + * add a container for Doctrine2 ORM + * run CI testing on travis + ## TODO - * add a container for Doctrine2 (ORM or DBAL?) * add support for Swiftmailer * investigate better queues than RDBMS diff --git a/src/PEAR2/Mail/Queue/Container/doctrine2.php b/src/PEAR2/Mail/Queue/Container/doctrine2.php index f4e2231..b184904 100644 --- a/src/PEAR2/Mail/Queue/Container/doctrine2.php +++ b/src/PEAR2/Mail/Queue/Container/doctrine2.php @@ -53,6 +53,7 @@ use PEAR2\Mail\Queue; use PEAR2\Mail\Queue\Body; use PEAR2\Mail\Queue\Entity\Mail; +use PEAR2\Mail\Queue\Entity\Repository\MailRepository; use Doctrine\ORM\EntityManager; use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Common\Persistence\PersistentObject; @@ -77,16 +78,23 @@ class Doctrine2 extends Container { + var $errorMsg = 'doctrine failed: "%s", %s'; + /** * @var Doctrine\ORM\EntityManager */ protected $em; /** - * @var Entity Classname + * @var Mail Mail */ protected $entity; + /** + * @var MailRepository MailRepository + */ + protected $repo; + /** * @var */ @@ -115,11 +123,18 @@ public function __construct(array $options) if (isset($options['em'])) { $this->em = $options['em']; + //$this->init($options['em']); } else { $this->em = $this->getEntityManager(); } + //var_dump($this->em->getConfiguration()->getMetadataDriverImpl()); + //exit; + //$this->em->getConfiguration()->setMetadataDriverImpl() + $this->setOption(); + $this->repo = $this->em->getRepository('PEAR2\Mail\Queue\Entity\Mail'); + } /** @@ -127,14 +142,43 @@ public function __construct(array $options) * * @return void */ - protected function init() + protected function init($em = null, $entity = null) { + //use injected entity + if(isset($entity)){ + + }else{ + + } + + //use injected em + if(isset($em)){ + + }else{ + + } + + if(isset($em) + && 'Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain' == get_class($em->getConfiguration()->getMetadataDriverImpl()) + ){ + foreach($em->getConfiguration()->getMetadataDriverImpl()->getDrivers() as $driver){ + if(in_array('',$driver->getAllClassNames())){ + + } + + } + } + $config = new Configuration(); $cache = new $this->config['cacheImplementation']; + + $mappingDriverChain = new \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain(); + $entityFolder = __DIR__ . '/../Entity'; $driverImpl = $config->newDefaultAnnotationDriver($entityFolder); + AnnotationReader::addGlobalIgnoredName('package_version'); $annotationReader = new AnnotationReader; $cachedAnnotationReader = new \Doctrine\Common\Annotations\CachedReader( @@ -147,6 +191,7 @@ protected function init() array($entityFolder) // paths to look in ); + //$mappingDriverChain->addDriver($annotationDriver, 'PEAR2\Mail\Queue\Entity'); $config->setMetadataDriverImpl($annotationDriver); $config->setMetadataCacheImpl($cache); @@ -169,7 +214,7 @@ protected function init() /** * Get the Doctrine EntityManager * - * @return Doctrine\ORM\EntityManager + * @return \Doctrine\ORM\EntityManager */ public function getEntityManager() { @@ -201,7 +246,32 @@ public function setEntityManager($em) */ protected function _preload() { - // TODO: Implement _preload() method. + $queueCollection = $this->repo->preload($this->limit, $this->offset,$this->try); + + $this->_last_item = 0; + $this->queue_data = array(); //reset buffer + + foreach($queueCollection as $mail){ + $delete_after_send = (bool) $mail->__get('deleteAfterSend'); + + $this->queue_data[$this->_last_item] = new Body( + $mail->getId(), + $mail->getCreateTime(), + $mail->getTimeToSend(), + $mail->getSentTime(), + $mail->getIdUser(), + $mail->getIp(), + $mail->getSender(), + $this->_isSerialized($mail->getRecipient()) ? unserialize($mail->getRecipient()) : $mail->getRecipient(), + unserialize($mail->getHeaders()), + unserialize($mail->getBody()), + $delete_after_send, + $mail->getTrySent() + ); + $this->_last_item++; + } + + return true; } /** @@ -239,8 +309,6 @@ public function put($time_to_send, $id_user, $ip, $from, $to, $hdrs, $body, $del $this->em->flush(); return $queueRecord->__get('id'); - - // TODO: Implement put() method. } /** @@ -252,6 +320,24 @@ public function put($time_to_send, $id_user, $ip, $from, $to, $hdrs, $body, $del */ public function countSend(Body $mail) { + $count = $mail->_try(); + + $mailRecord = $this->repo->find($mail->getId()); + + if (null == $mailRecord) { + throw new Exception( + sprintf($this->errorMsg, $mail->getId(), 'no message with id'), + Queue::ERROR_QUERY_FAILED + ); + } + + $mailRecord->__set('trySent',$count); + $this->em->persist($mailRecord); + $this->em->flush(); + + + return $count; + // TODO: Implement countSend() method. } @@ -264,8 +350,22 @@ public function countSend(Body $mail) */ public function setAsSent(Body $mail) { - // TODO: Implement setAsSent() method. - return $this; + $mailRecord = $this->repo->find($mail->getId()); + + if (null == $mailRecord) { + throw new Exception( + sprintf($this->errorMsg, $mail->getId(), 'no message with id'), + Queue::ERROR_QUERY_FAILED + ); + } + + $now = new \DateTime(); + $mailRecord->__set('sentTime',$now); + + $this->em->persist($mailRecord); + $this->em->flush(); + + return true; } @@ -278,8 +378,7 @@ public function setAsSent(Body $mail) */ public function getMailById($id) { - $repo = $this->em->getRepository('PEAR2\Mail\Queue\Entity\Mail'); - $mailRecord = $repo->find($id); + $mailRecord = $this->repo->find($id); if (null == $mailRecord) { throw new Exception( @@ -312,6 +411,9 @@ public function getMailById($id) */ public function getQueueCount() { + $count = $this->repo->getQueueCount(); + return (int) $count; + // TODO: Implement getQueueCount() method. } @@ -324,6 +426,18 @@ public function getQueueCount() */ public function deleteMail($id) { - // TODO: Implement deleteMail() method. + $mailRecord = $this->repo->find($id); + + if (null == $mailRecord) { + throw new Exception( + sprintf($this->errorMsg, $id, 'no message with id'), + Queue::ERROR_QUERY_FAILED + ); + } + + $this->em->remove($mailRecord); + $this->em->flush(); + + return true; } } diff --git a/src/PEAR2/Mail/Queue/Entity/Mail.php b/src/PEAR2/Mail/Queue/Entity/Mail.php index 4c1fdeb..d165e6c 100644 --- a/src/PEAR2/Mail/Queue/Entity/Mail.php +++ b/src/PEAR2/Mail/Queue/Entity/Mail.php @@ -11,7 +11,7 @@ */ class Mail { - + /** * @ORM\Column(name="id", type="integer") * @ORM\Id @@ -77,10 +77,18 @@ class Mail private $deleteAfterSend; /** - * @ORM\Column(name="try_sent", type="integer", nullable=true) + * @ORM\Column(name="try_sent", type="integer", options={"default" = 0}) */ private $trySent; + /** + * construct + */ + public function __construct() + { + $this->trySent = 0; + } + /** * Magic getter to expose protected properties. * diff --git a/src/PEAR2/Mail/Queue/Entity/Repository/MailRepository.php b/src/PEAR2/Mail/Queue/Entity/Repository/MailRepository.php index dd4eb06..29426c5 100644 --- a/src/PEAR2/Mail/Queue/Entity/Repository/MailRepository.php +++ b/src/PEAR2/Mail/Queue/Entity/Repository/MailRepository.php @@ -8,5 +8,40 @@ */ class MailRepository extends EntityRepository { + public function preload($limit, $offset, $try) + { + $query = $this->_em->createQuery( + 'SELECT m FROM PEAR2\Mail\Queue\Entity\Mail m' + . ' WHERE' + . ' m.sentTime is NULL AND' + . ' m.trySent < :try AND' + . ' m.timeToSend <= :timeToSend' + . ' ORDER BY m.timeToSend' + ); + + if($limit){ + $query->setMaxResults($limit); + } + + if($offset){ + $query->setFirstResult($offset); + } + + $query + ->setParameter('timeToSend', new \DateTime()) + ->setParameter('try', $try); + + return $query->getResult(); + + } + + public function getQueueCount() + { + + $query = $this->_em->createQuery('SELECT COUNT(m.id) FROM PEAR2\Mail\Queue\Entity\Mail m'); + $count = $query->getSingleScalarResult(); + + return $count; + } } diff --git a/tests/Mail/Queue/DoctrineContainerTest.php b/tests/Mail/Queue/DoctrineContainerTest.php index 7c8e958..4faa725 100644 --- a/tests/Mail/Queue/DoctrineContainerTest.php +++ b/tests/Mail/Queue/DoctrineContainerTest.php @@ -36,4 +36,168 @@ public function testContainerGet() $this->assertTrue($message->isDeleteAfterSend()); } + + public function testGetMailById(){ + + $id_user = 1; + $sender = 'testsuite@example.org'; + $recipient = 'testcase@example.org'; + $headers = array('X-TestSuite' => 1); + $body = 'Lorem ipsum'; + + $mailId = $this->queue->put($sender, $recipient, $headers, $body, 0, true, $id_user); + if (!is_numeric($mailId)) { + $this->fail("Could not save email."); + return; + } + $message = $this->queue->sendMailById($mailId); + $this->assertEquals($message, true); + } + + /** + * @expectedException Exception + */ + public function testDeleteMailById(){ + + $id_user = 1; + $sender = 'testsuite@example.org'; + $recipient = 'testcase@example.org'; + $headers = array('X-TestSuite' => 1); + $body = 'Lorem ipsum'; + + $mailId = $this->queue->put($sender, $recipient, $headers, $body, 0, true, $id_user); + if (!is_numeric($mailId)) { + $this->fail("Could not save email."); + return; + } + $delResult = $this->getContainer()->deleteMail($mailId); + + $this->assertEquals($delResult, true); + + $findResult = $delResult = $this->getContainer()->getMailById($mailId); + + $this->assertEquals($findResult, false); + + + } + + public function testPut() + { + $id_user = 1; + $ip = '127.0.0.1'; + $sender = 'testsuite@example.org'; + $recipient = 'testcase@example.org'; + $headers = array('X-TestSuite' => 1); + $body = 'Lorem ipsum'; + + $mailId = $this->queue->put($sender, $recipient, $headers, $body, 0, true, $id_user); + if (!is_numeric($mailId)) { + $this->handlePearError($mailId, "Could not save email."); + } + + $this->assertEquals(1, $mailId); // it's the first email, after all :-) + $this->assertEquals(1, count($this->queue->getQueueCount())); + } + + /** + * Arrays with from, to, headers, body and when to send (= now). + * + * @return void + */ + public function testLimit() + { + $emails = array( + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + array('from@example.org', 'to@example.org', array('X-Test' => 'yes'), 'Hello World', 0), + ); + + foreach ($emails as $email) { + $id = call_user_func_array(array($this->queue, 'put'), $email); + $this->assertInternalType('int', $id); + } + $this->assertEquals(count($emails), $this->queue->getQueueCount()); + + $this->queue->setBufferSize(2); + $this->assertTrue($this->queue->sendMailsInQueue(12)); + + $this->assertEquals(3, $this->queue->getQueueCount()); + + $this->assertFalse($this->queue->hasErrors()); + } + + /** + * This should return a MDB2_Error + * + * @expectedException PEAR2\Mail\Queue\Exception + */ + public function testSendMailByIdWithInvalidId() + { + $randomId = rand(1, 12); + $status = $this->queue->sendMailById($randomId); + } + + /** + * Queue two emails - to be send right away. + * + * @return void + */ + public function testSendMailsInQueue() + { + $id_user = 1; + $sender = 'testsuite@example.org'; + $recipient = 'testcase@example.org'; + $headers = array('X-TestSuite' => 1); + $body = 'Lorem ipsum'; + + $mailId1 = $this->queue->put($sender, $recipient, $headers, $body); + if ($mailId1 instanceof PEAR_Error) { + $this->fail("Queueing first mail failed: {$mailId1->getMessage()}"); + return; + } + + $id_user = 1; + $sender = 'testsuite@example.org'; + $recipient = 'testcase@example.org'; + $headers = array('X-TestSuite' => 2); + $body = 'Lorem ipsum sit dolor'; + + $mailId2 = $this->queue->put($sender, $recipient, $headers, $body); + if ($mailId2 instanceof PEAR_Error) { + $this->fail("Queueing first mail failed: {$mailId2->getMessage()}"); + return; + } + + $queueCount = $this->queue->getQueueCount(); + if ($this->queue->hasErrors()) { + $fail = ''; + foreach ($this->queue->getErrors() as $error) { + $fail .= $error->getMessage() . ", "; + } + $this->fail("Errors from getQueueCount: {$fail}"); + return; + } + $this->assertEquals(2, $queueCount, "Failed to count 2 messages."); + + $status = $this->queue->sendMailsInQueue(); + if ($status instanceof PEAR_Error) { + $this->fail("Error sending emails: {$status->getMessage()}."); + return; + } + + $this->assertTrue($status); + $this->assertEquals(0, $this->queue->getQueueCount(), "Mails did not get removed?"); + } } diff --git a/tests/Mail/QueueDoctrineAbstract.php b/tests/Mail/QueueDoctrineAbstract.php index 16c90a8..bfe462a 100644 --- a/tests/Mail/QueueDoctrineAbstract.php +++ b/tests/Mail/QueueDoctrineAbstract.php @@ -7,6 +7,7 @@ */ abstract class Mail_QueueDoctrineAbstract extends PHPUnit_Framework_TestCase { + protected $container; /** * @var Doctrine\ORM\EntityManager */ @@ -40,6 +41,7 @@ public function setUp() ); $doctrineDriver = new PEAR2\Mail\Queue\Container\doctrine2(array('doctrine' => $doctrineConfig)); + $this->container = $doctrineDriver; $this->em = $doctrineDriver->getEntityManager(); @@ -98,4 +100,7 @@ public function tearDown() unset($this->queue); } + public function getContainer(){ + return $this->container; + } } From d4c1bc6e72c7406b747e9e668b67bf35cc2fb8a5 Mon Sep 17 00:00:00 2001 From: Leander Date: Thu, 29 Nov 2012 22:13:33 +0100 Subject: [PATCH 6/8] inject doctrine entity manager removed em setup --- src/PEAR2/Mail/Queue/Container/doctrine2.php | 100 +------------------ tests/Mail/QueueDoctrineAbstract.php | 58 ++++++++--- 2 files changed, 47 insertions(+), 111 deletions(-) diff --git a/src/PEAR2/Mail/Queue/Container/doctrine2.php b/src/PEAR2/Mail/Queue/Container/doctrine2.php index b184904..c8f045b 100644 --- a/src/PEAR2/Mail/Queue/Container/doctrine2.php +++ b/src/PEAR2/Mail/Queue/Container/doctrine2.php @@ -54,12 +54,6 @@ use PEAR2\Mail\Queue\Body; use PEAR2\Mail\Queue\Entity\Mail; use PEAR2\Mail\Queue\Entity\Repository\MailRepository; -use Doctrine\ORM\EntityManager; -use Doctrine\Common\Annotations\AnnotationRegistry; -use Doctrine\Common\Persistence\PersistentObject; -use Doctrine\ORM\Configuration; - -use Doctrine\Common\Annotations\AnnotationReader; /** * Storage driver for fetching mail queue data with Doctrine2 @@ -107,108 +101,20 @@ class Doctrine2 extends Container * * @param array $options An associative array of connection option. * - * @return hmmm */ public function __construct(array $options) { - if (!isset($options['doctrine'])) { + if (!isset($options['doctrine_em'])) { throw new Exception( - 'No doctrine config specified!', + 'No doctrine entity manager specified!', Queue::ERROR_NO_OPTIONS ); } - - $this->config = $options['doctrine']; - - if (isset($options['em'])) { - $this->em = $options['em']; - //$this->init($options['em']); - } else { - $this->em = $this->getEntityManager(); - } - - //var_dump($this->em->getConfiguration()->getMetadataDriverImpl()); - //exit; - //$this->em->getConfiguration()->setMetadataDriverImpl() + $this->em = $options['doctrine_em']; $this->setOption(); $this->repo = $this->em->getRepository('PEAR2\Mail\Queue\Entity\Mail'); - - } - - /** - * Setup Doctrine Class Loaders & EntityManager - * - * @return void - */ - protected function init($em = null, $entity = null) - { - - //use injected entity - if(isset($entity)){ - - }else{ - - } - - //use injected em - if(isset($em)){ - - }else{ - - } - - if(isset($em) - && 'Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain' == get_class($em->getConfiguration()->getMetadataDriverImpl()) - ){ - foreach($em->getConfiguration()->getMetadataDriverImpl()->getDrivers() as $driver){ - if(in_array('',$driver->getAllClassNames())){ - - } - - } - } - - $config = new Configuration(); - $cache = new $this->config['cacheImplementation']; - - $mappingDriverChain = new \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain(); - - $entityFolder = __DIR__ . '/../Entity'; - $driverImpl = $config->newDefaultAnnotationDriver($entityFolder); - - - AnnotationReader::addGlobalIgnoredName('package_version'); - $annotationReader = new AnnotationReader; - $cachedAnnotationReader = new \Doctrine\Common\Annotations\CachedReader( - $annotationReader, // use reader - $cache // and a cache driver - ); - - $annotationDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver( - $cachedAnnotationReader, // our cached annotation reader - array($entityFolder) // paths to look in - ); - - //$mappingDriverChain->addDriver($annotationDriver, 'PEAR2\Mail\Queue\Entity'); - - $config->setMetadataDriverImpl($annotationDriver); - $config->setMetadataCacheImpl($cache); - $config->setQueryCacheImpl($cache); - $config->setProxyDir(__DIR__ . '/../Proxy'); - $config->setProxyNamespace($this->config['proxy']['namespace']); - $config->setAutoGenerateProxyClasses($this->config['autoGenerateProxyClasses']); - - $connectionConfig = $this->config['connection']; - - $this->em = EntityManager::create( - $connectionConfig, - $config - ); - - PersistentObject::setObjectManager($this->em); - return; } /** diff --git a/tests/Mail/QueueDoctrineAbstract.php b/tests/Mail/QueueDoctrineAbstract.php index bfe462a..5f95464 100644 --- a/tests/Mail/QueueDoctrineAbstract.php +++ b/tests/Mail/QueueDoctrineAbstract.php @@ -1,6 +1,11 @@ 'Doctrine\Common\Cache\ArrayCache', - 'connection' => array( - 'driver' => 'pdo_sqlite', - 'dbname' => '', - 'user' => '', - 'host' => '', + $config = new Configuration(); + $cache = new \Doctrine\Common\Cache\ArrayCache(); + $config->newDefaultAnnotationDriver(); + + AnnotationReader::addGlobalIgnoredName('package_version'); + $annotationReader = new AnnotationReader; + $cachedAnnotationReader = new \Doctrine\Common\Annotations\CachedReader( + $annotationReader, // use reader + $cache // and a cache driver + ); + + $annotationDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver( + $cachedAnnotationReader//, // our cached annotation reader + //array($entityFolder) // paths to look in + ); + + //$mappingDriverChain->addDriver($annotationDriver, 'PEAR2\Mail\Queue\Entity'); + + $config->setMetadataDriverImpl($annotationDriver); + $config->setMetadataCacheImpl($cache); + $config->setQueryCacheImpl($cache); + $config->setProxyDir(__DIR__ . '/../Proxy'); + $config->setProxyNamespace('testProxy'); + $config->setAutoGenerateProxyClasses(1); + + $connectionConfig = array( + 'driver' => 'pdo_sqlite', + 'dbname' => '', + 'user' => '', + 'host' => '', 'password' => '', - 'memory' => true - ), - 'autoGenerateProxyClasses' => 1, - 'proxy' => array('namespace' => 'Proxy') + 'memory' => true + + ); + + $this->em = EntityManager::create( + $connectionConfig, + $config ); - $doctrineDriver = new PEAR2\Mail\Queue\Container\doctrine2(array('doctrine' => $doctrineConfig)); + $doctrineDriver = new PEAR2\Mail\Queue\Container\doctrine2(array('doctrine_em' => $this->em)); $this->container = $doctrineDriver; $this->em = $doctrineDriver->getEntityManager(); @@ -50,8 +81,7 @@ public function setUp() $container_opts = array( 'type' => 'doctrine2', - 'doctrine' => $doctrineConfig, - 'em' => $this->em + 'doctrine_em' => $this->em ); /** From 41149a3aea17b52f8b19346ccb175f36d60dbd26 Mon Sep 17 00:00:00 2001 From: Leander Date: Thu, 29 Nov 2012 22:14:22 +0100 Subject: [PATCH 7/8] removed obsolete stuff --- tests/Mail/QueueDoctrineAbstract.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/Mail/QueueDoctrineAbstract.php b/tests/Mail/QueueDoctrineAbstract.php index 5f95464..31cfc8e 100644 --- a/tests/Mail/QueueDoctrineAbstract.php +++ b/tests/Mail/QueueDoctrineAbstract.php @@ -44,11 +44,8 @@ public function setUp() $annotationDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver( $cachedAnnotationReader//, // our cached annotation reader - //array($entityFolder) // paths to look in ); - //$mappingDriverChain->addDriver($annotationDriver, 'PEAR2\Mail\Queue\Entity'); - $config->setMetadataDriverImpl($annotationDriver); $config->setMetadataCacheImpl($cache); $config->setQueryCacheImpl($cache); From ceb05ded474c8f0efff0909fd2ae758fce4fd89d Mon Sep 17 00:00:00 2001 From: Leander Date: Thu, 29 Nov 2012 22:41:43 +0100 Subject: [PATCH 8/8] install MDB2_Driver_sqlite --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 4dcee33..9bccf03 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,7 @@ ], "require": { "pear-pear/MDB2": "2.5.0b5", + "pear-pear/MDB2_Driver_sqlite": "*", "pear-pear/Mail": "*", "pear-pear/Mail_Mime": "*", "doctrine/orm": "2.4.x-dev"