1<?php
2
3/**
4 * Swift Mailer Throttling Plugin.
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_Plugin_BandwidthMonitor");
13Swift_ClassLoader::load("Swift_Events_SendListener");
14
15/**
16 * Throttler plugin for Swift Mailer.
17 * Restricts the speed at which Swift will operate.
18 * @package Swift_Plugin
19 * @author Chris Corbyn <chris@w3style.co.uk>
20 */
21class Swift_Plugin_Throttler extends Swift_Plugin_BandwidthMonitor implements Swift_Events_SendListener
22{
23  /**
24   * The rate in byte-per-minute
25   * @var int
26   */
27  protected $bpm = null;
28  /**
29   * The rate as emails-per-minute
30   * @var int
31   */
32  protected $epm = null;
33  /**
34   * The number of emails sent so far
35   * @var int
36   */
37  protected $sent = 0;
38  /**
39   * The time at the start of overall execution
40   * @var int
41   */
42  protected $time = null;
43
44  /**
45   * Part of the interface which is notified after a command is sent.
46   * @param Swift_Events_CommandEvent
47   */
48  public function commandSent(Swift_Events_CommandEvent $e)
49  {
50    parent::commandSent($e);
51    if (null === $rate = $this->getBytesPerMinute()) return;
52
53    $duration = $this->getTimeLapse();
54    $bytes_sent = $this->getBytesOut();
55    $bytes_per_sec = $rate / 60;
56    $seconds_allowed_so_far = ceil($bytes_sent / $bytes_per_sec);
57    $overrun = $seconds_allowed_so_far - $duration;
58    if ($overrun > 0)
59    {
60      $this->wait($overrun);
61    }
62  }
63  /**
64   * Part of the interface which is notified when a message has been sent.
65   * @param Swift_Events_SendEvent
66   */
67  public function sendPerformed(Swift_Events_SendEvent $e)
68  {
69    $this->setSent($this->getSent() + 1);
70    if (null === $rate = $this->getEmailsPerMinute()) return;
71
72    $duration = $this->getTimeLapse();
73    $emails_sent = $this->getSent();
74    $emails_per_sec = $rate / 60;
75    $seconds_allowed_so_far = ceil($emails_sent / $emails_per_sec);
76    $overrun = $seconds_allowed_so_far - $duration;
77    if ($overrun > 0)
78    {
79      $this->wait($overrun);
80    }
81  }
82  /**
83   * Wait for $seconds before continuing
84   * @param int The number of seconds to wait
85   */
86  public function wait($secs)
87  {
88    sleep($secs);
89  }
90  /**
91   * Set the time if it's not already set
92   */
93  protected function setTime()
94  {
95    if ($this->time === null) $this->time = time();
96  }
97  /**
98   * Get the time taken thus far (full seconds).
99   * @return int
100   */
101  public function getTimeLapse()
102  {
103    $this->setTime();
104    return time() - $this->time;
105  }
106  /**
107   * Set the number of emails sent
108   * @param int Emails sent so far
109   */
110  public function setSent($num)
111  {
112    $this->sent = (int)$num;
113  }
114  /**
115   * Get the number of emails sent
116   * @return int
117   */
118  public function getSent()
119  {
120    return $this->sent;
121  }
122  /**
123   * Set the throttling rate as bytes per minute
124   * @param int The maximum number of outgoing bytes in 60 seconds.
125   */
126  public function setBytesPerMinute($bpm)
127  {
128    if ($bpm === null)
129    {
130      $this->bpm = null;
131      return;
132    }
133    $this->setEmailsPerMinute(null);
134    $this->bpm = abs((int)$bpm);
135  }
136  /**
137   * Get the number of bytes allowed per minute.
138   * Reurns NULL if not used.
139   * @return int
140   */
141  public function getBytesPerMinute()
142  {
143    return $this->bpm;
144  }
145  /**
146   * Set the rate as emails-per-minute.
147   * @param int The max number of emails to send in a minute.
148   */
149  public function setEmailsPerMinute($epm)
150  {
151    if ($epm === null)
152    {
153      $this->epm = null;
154      return;
155    }
156    $this->setBytesPerMinute(null);
157    $this->epm = abs((int)$epm);
158  }
159  /**
160   * Get the rate as number of emails per minute.
161   * Returns null if not used.
162   * @return int
163   */
164  public function getEmailsPerMinute()
165  {
166    return $this->epm;
167  }
168}
169