1<?php
2
3/**
4 * Swift Mailer Multiple Redundant Connection component.
5 * Please read the LICENSE file
6 * @author Chris Corbyn <chris@w3style.co.uk>
7 * @package Swift_Connection
8 * @license GNU Lesser General Public License
9 */
10
11require_once dirname(__FILE__) . "/../ClassLoader.php";
12Swift_ClassLoader::load("Swift_ConnectionBase");
13
14/**
15 * Swift Multi Connection
16 * Tries to connect to a number of connections until one works successfully
17 * @package Swift_Connection
18 * @author Chris Corbyn <chris@w3style.co.uk>
19 */
20class Swift_Connection_Multi extends Swift_ConnectionBase
21{
22  /**
23   * The list of available connections
24   * @var array
25   */
26  protected $connections = array();
27  /**
28   * The id of the active connection
29   * @var string
30   */
31  protected $active = null;
32
33  /**
34   * Constructor
35   */
36  public function __construct($connections=array())
37  {
38    foreach ($connections as $id => $conn)
39    {
40      $this->addConnection($connections[$id], $id);
41    }
42  }
43  /**
44   * Add a connection to the list of options
45   * @param Swift_Connection An instance of the connection
46   * @param string An ID to assign to the connection
47   */
48  public function addConnection(Swift_Connection $connection, $id=null)
49  {
50    $log = Swift_LogContainer::getLog();
51    if ($log->hasLevel(Swift_Log::LOG_EVERYTHING))
52    {
53      $log->add("Adding new connection of type '" . get_class($connection) . "' to the multi-redundant connection.");
54    }
55    if ($id !== null) $this->connections[$id] = $connection;
56    else $this->connections[] = $connection;
57  }
58  /**
59   * Read a full response from the buffer
60   * @return string
61   * @throws Swift_ConnectionException Upon failure to read
62   */
63  public function read()
64  {
65    if ($this->active === null)
66    {
67      throw new Swift_ConnectionException("None of the connections set have been started");
68    }
69    return $this->connections[$this->active]->read();
70  }
71  /**
72   * Write a command to the server (leave off trailing CRLF)
73   * @param string The command to send
74   * @throws Swift_ConnectionException Upon failure to write
75   */
76  public function write($command, $end="\r\n")
77  {
78    if ($this->active === null)
79    {
80      throw new Swift_ConnectionException("None of the connections set have been started");
81    }
82    return $this->connections[$this->active]->write($command, $end);
83  }
84  /**
85   * Try to start the connection
86   * @throws Swift_ConnectionException Upon failure to start
87   */
88  public function start()
89  {
90    $log = Swift_LogContainer::getLog();
91    $fail_messages = array();
92    foreach ($this->connections as $id => $conn)
93    {
94      try {
95        $this->connections[$id]->start();
96        if ($this->connections[$id]->isAlive())
97        {
98          $this->active = $id;
99          return true;
100        }
101        else
102        {
103          if ($log->hasLevel(Swift_Log::LOG_EVERYTHING))
104          {
105            $log->add("Connection (" . $id . ") failed. Will try next connection if available.");
106          }
107          throw new Swift_ConnectionException("The connection started but reported that it was not active");
108        }
109      } catch (Swift_ConnectionException $e) {
110        $fail_messages[] = $id . ": " . $e->getMessage();
111      }
112    }
113    $failure = implode("<br />", $fail_messages);
114    throw new Swift_ConnectionException($failure);
115  }
116  /**
117   * Try to close the connection
118   * @throws Swift_ConnectionException Upon failure to close
119   */
120  public function stop()
121  {
122    if ($this->active !== null) $this->connections[$this->active]->stop();
123    $this->active = null;
124  }
125  /**
126   * Check if the current connection is alive
127   * @return boolean
128   */
129  public function isAlive()
130  {
131    return (($this->active !== null) && $this->connections[$this->active]->isAlive());
132  }
133  /**
134   * Call the current connection's postConnect() method
135   */
136  public function postConnect(Swift $instance)
137  {
138    $this->connections[$this->active]->postConnect($instance);
139  }
140  /**
141   * Call the current connection's setExtension() method
142   */
143  public function setExtension($extension, $attributes=array())
144  {
145    $this->connections[$this->active]->setExtension($extension, $attributes);
146  }
147  /**
148   * Call the current connection's hasExtension() method
149   */
150  public function hasExtension($name)
151  {
152    return $this->connections[$this->active]->hasExtension($name);
153  }
154  /**
155   * Call the current connection's getAttributes() method
156   */
157  public function getAttributes($name)
158  {
159    return $this->connections[$this->active]->getAttributes($name);
160  }
161}
162