1: <?php
2:
3: /*
4: * This file is part of SwiftMailer.
5: * (c) 2004-2009 Chris Corbyn
6: *
7: * For the full copyright and license information, please view the LICENSE
8: * file that was distributed with this source code.
9: */
10:
11: /**
12: * Throttles the rate at which emails are sent.
13: * @package Swift
14: * @subpackage Plugins
15: * @author Chris Corbyn
16: */
17: class Swift_Plugins_ThrottlerPlugin extends Swift_Plugins_BandwidthMonitorPlugin implements Swift_Plugins_Sleeper, Swift_Plugins_Timer
18: {
19: /** Flag for throttling in bytes per minute */
20: const BYTES_PER_MINUTE = 0x01;
21:
22: /** Flag for throttling in emails per minute */
23: const MESSAGES_PER_MINUTE = 0x10;
24:
25: /**
26: * The Sleeper instance for sleeping.
27: * @var Swift_Plugins_Sleeper
28: * @access private
29: */
30: private $_sleeper;
31:
32: /**
33: * The Timer instance which provides the timestamp.
34: * @var Swift_Plugins_Timer
35: * @access private
36: */
37: private $_timer;
38:
39: /**
40: * The time at which the first email was sent.
41: * @var int
42: * @access private
43: */
44: private $_start;
45:
46: /**
47: * The rate at which messages should be sent.
48: * @var int
49: * @access private
50: */
51: private $_rate;
52:
53: /**
54: * The mode for throttling.
55: * This is {@link BYTES_PER_MINUTE} or {@link MESSAGES_PER_MINUTE}
56: * @var int
57: * @access private
58: */
59: private $_mode;
60:
61: /**
62: * An internal counter of the number of messages sent.
63: * @var int
64: * @access private
65: */
66: private $_messages = 0;
67:
68: /**
69: * Create a new ThrottlerPlugin.
70: * @param int $rate
71: * @param int $mode, defaults to {@link BYTES_PER_MINUTE}
72: * @param Swift_Plugins_Sleeper $sleeper (only needed in testing)
73: * @param Swift_Plugins_Timer $timer (only needed in testing)
74: */
75: public function __construct($rate, $mode = self::BYTES_PER_MINUTE, Swift_Plugins_Sleeper $sleeper = null, Swift_Plugins_Timer $timer = null)
76: {
77: $this->_rate = $rate;
78: $this->_mode = $mode;
79: $this->_sleeper = $sleeper;
80: $this->_timer = $timer;
81: }
82:
83: /**
84: * Invoked immediately before the Message is sent.
85: * @param Swift_Events_SendEvent $evt
86: */
87: public function beforeSendPerformed(Swift_Events_SendEvent $evt)
88: {
89: $time = $this->getTimestamp();
90: if (!isset($this->_start)) {
91: $this->_start = $time;
92: }
93: $duration = $time - $this->_start;
94:
95: if (self::BYTES_PER_MINUTE == $this->_mode) {
96: $sleep = $this->_throttleBytesPerMinute($duration);
97: } else {
98: $sleep = $this->_throttleMessagesPerMinute($duration);
99: }
100:
101: if ($sleep > 0) {
102: $this->sleep($sleep);
103: }
104: }
105:
106: /**
107: * Invoked when a Message is sent.
108: * @param Swift_Events_SendEvent $evt
109: */
110: public function sendPerformed(Swift_Events_SendEvent $evt)
111: {
112: parent::sendPerformed($evt);
113: ++$this->_messages;
114: }
115:
116: /**
117: * Sleep for $seconds.
118: * @param int $seconds
119: */
120: public function sleep($seconds)
121: {
122: if (isset($this->_sleeper)) {
123: $this->_sleeper->sleep($seconds);
124: } else {
125: sleep($seconds);
126: }
127: }
128:
129: /**
130: * Get the current UNIX timestamp
131: * @return int
132: */
133: public function getTimestamp()
134: {
135: if (isset($this->_timer)) {
136: return $this->_timer->getTimestamp();
137: } else {
138: return time();
139: }
140: }
141:
142: // -- Private methods
143:
144: /**
145: * Get a number of seconds to sleep for.
146: * @param int $timePassed
147: * @return int
148: * @access private
149: */
150: private function _throttleBytesPerMinute($timePassed)
151: {
152: $expectedDuration = $this->getBytesOut() / ($this->_rate / 60);
153:
154: return (int) ceil($expectedDuration - $timePassed);
155: }
156:
157: /**
158: * Get a number of seconds to sleep for.
159: * @param int $timePassed
160: * @return int
161: * @access private
162: */
163: private function _throttleMessagesPerMinute($timePassed)
164: {
165: $expectedDuration = $this->_messages / ($this->_rate / 60);
166:
167: return (int) ceil($expectedDuration - $timePassed);
168: }
169: }
170: