1<?php
2
3/**
4 * Swift Mailer Rotating Connection Controller
5 * Please read the LICENSE file
6 * @author Chris Corbyn <chris@w3style.co.uk>
7 * @package Swift_Plugin
8 * @license GNU Lesser General Public License
9 */
10
11require_once dirname(__FILE__) . "/../ClassLoader.php";
12Swift_ClassLoader::load("Swift_Events_SendListener");
13Swift_ClassLoader::load("Swift_Events_DisconnectListener");
14
15/**
16 * Swift Rotating Connection Controller
17 * Invokes the nextConnection() method of Swift_Connection_Rotator upon sending a given number of messages
18 * @package Swift_Plugin
19 * @author Chris Corbyn <chris@w3style.co.uk>
20 */
21class Swift_Plugin_ConnectionRotator implements Swift_Events_SendListener, Swift_Events_DisconnectListener
22{
23  /**
24   * The number of emails which must be sent before the connection is rotated
25   * @var int Threshold number of emails
26   */
27  protected $threshold = 1;
28  /**
29   * The total number of emails sent on this connection
30   * @var int
31   */
32  protected $count = 0;
33  /**
34   * The connections we have used thus far
35   * @var array
36   */
37  protected $used = array();
38  /**
39   * Internal check to see if this plugin has yet been invoked
40   * @var boolean
41   */
42  protected $called = false;
43
44  /**
45   * Constructor
46   * @param int The number of emails to send before rotating
47   */
48  public function __construct($threshold=1)
49  {
50    $this->setThreshold($threshold);
51  }
52  /**
53   * Set the number of emails to send before a connection rotation is tried
54   * @param int Number of emails
55   */
56  public function setThreshold($threshold)
57  {
58    $this->threshold = (int) $threshold;
59  }
60  /**
61   * Get the number of emails which must be sent before a rotation occurs
62   * @return int
63   */
64  public function getThreshold()
65  {
66    return $this->threshold;
67  }
68  /**
69   * Swift's SendEvent listener.
70   * Invoked when Swift sends a message
71   * @param Swift_Events_SendEvent The event information
72   * @throws Swift_ConnectionException If the connection cannot be rotated
73   */
74  public function sendPerformed(Swift_Events_SendEvent $e)
75  {
76    if (!method_exists($e->getSwift()->connection, "nextConnection"))
77    {
78      throw new Swift_ConnectionException("The ConnectionRotator plugin cannot be used with connections other than Swift_Connection_Rotator.");
79    }
80    if (!$this->called)
81    {
82      $this->used[] = $e->getSwift()->connection->getActive();
83    }
84    $this->count++;
85    if ($this->count >= $this->getThreshold())
86    {
87      $e->getSwift()->connection->nextConnection();
88      if (!in_array(($id = $e->getSwift()->connection->getActive()), $this->used))
89      {
90        $e->getSwift()->connect();
91        $this->used[] = $id;
92      }
93      $this->count = 0;
94    }
95    $this->called = true;
96  }
97  /**
98   * Disconnect all the other connections
99   * @param Swift_Events_DisconnectEvent The event info
100   */
101  public function disconnectPerformed(Swift_Events_DisconnectEvent $e)
102  {
103    $active = $e->getConnection()->getActive();
104    $e->getConnection()->nextConnection();
105    while ($e->getConnection()->getActive() != $active)
106    {
107      $e->getSwift()->command("QUIT", 221);
108      $e->getConnection()->stop();
109      $e->getConnection()->nextConnection();
110    }
111    $this->used = array();
112  }
113}
114