TYPO3  7.6
FileSpool.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of SwiftMailer.
5  * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10 
18 {
20  private $_path;
21 
27  private $_retryLimit = 10;
28 
36  public function __construct($path)
37  {
38  $this->_path = $path;
39 
40  if (!file_exists($this->_path)) {
41  if (!mkdir($this->_path, 0777, true)) {
42  throw new Swift_IoException('Unable to create Path ['.$this->_path.']');
43  }
44  }
45  }
46 
52  public function isStarted()
53  {
54  return true;
55  }
56 
60  public function start()
61  {
62  }
63 
67  public function stop()
68  {
69  }
70 
78  public function setRetryLimit($limit)
79  {
80  $this->_retryLimit = $limit;
81  }
82 
92  public function queueMessage(Swift_Mime_Message $message)
93  {
94  $ser = serialize($message);
95  $fileName = $this->_path.'/'.$this->getRandomString(10);
96  for ($i = 0; $i < $this->_retryLimit; ++$i) {
97  /* We try an exclusive creation of the file. This is an atomic operation, it avoid locking mechanism */
98  $fp = @fopen($fileName.'.message', 'x');
99  if (false !== $fp) {
100  if (false === fwrite($fp, $ser)) {
101  return false;
102  }
103 
104  return fclose($fp);
105  } else {
106  /* The file already exists, we try a longer fileName */
107  $fileName .= $this->getRandomString(1);
108  }
109  }
110 
111  throw new Swift_IoException('Unable to create a file for enqueuing Message');
112  }
113 
119  public function recover($timeout = 900)
120  {
121  foreach (new DirectoryIterator($this->_path) as $file) {
122  $file = $file->getRealPath();
123 
124  if (substr($file, -16) == '.message.sending') {
125  $lockedtime = filectime($file);
126  if ((time() - $lockedtime) > $timeout) {
127  rename($file, substr($file, 0, -8));
128  }
129  }
130  }
131  }
132 
141  public function flushQueue(Swift_Transport $transport, &$failedRecipients = null)
142  {
143  $directoryIterator = new DirectoryIterator($this->_path);
144 
145  /* Start the transport only if there are queued files to send */
146  if (!$transport->isStarted()) {
147  foreach ($directoryIterator as $file) {
148  if (substr($file->getRealPath(), -8) == '.message') {
149  $transport->start();
150  break;
151  }
152  }
153  }
154 
155  $failedRecipients = (array) $failedRecipients;
156  $count = 0;
157  $time = time();
158  foreach ($directoryIterator as $file) {
159  $file = $file->getRealPath();
160 
161  if (substr($file, -8) != '.message') {
162  continue;
163  }
164 
165  /* We try a rename, it's an atomic operation, and avoid locking the file */
166  if (rename($file, $file.'.sending')) {
167  $message = unserialize(file_get_contents($file.'.sending'));
168 
169  $count += $transport->send($message, $failedRecipients);
170 
171  unlink($file.'.sending');
172  } else {
173  /* This message has just been catched by another process */
174  continue;
175  }
176 
177  if ($this->getMessageLimit() && $count >= $this->getMessageLimit()) {
178  break;
179  }
180 
181  if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit()) {
182  break;
183  }
184  }
185 
186  return $count;
187  }
188 
196  protected function getRandomString($count)
197  {
198  // This string MUST stay FS safe, avoid special chars
199  $base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
200  $ret = '';
201  $strlen = strlen($base);
202  for ($i = 0; $i < $count; ++$i) {
203  $ret .= $base[((int) rand(0, $strlen - 1))];
204  }
205 
206  return $ret;
207  }
208 }