Swift   F
last analyzed

Complexity

Total Complexity 95

Size/Duplication

Total Lines 465
Duplicated Lines 9.03 %

Coupling/Cohesion

Components 1
Dependencies 16

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 42
loc 465
rs 1.5789
wmc 95
lcom 1
cbo 16

19 Methods

Rating   Name   Duplication   Size   Complexity  
C __construct() 0 23 8
A initializeEventListenerContainer() 0 9 3
A attachPlugin() 0 9 3
A getPlugin() 0 8 3
A removePlugin() 0 11 3
A notifyListeners() 0 13 4
A hasOption() 0 4 1
A setOptions() 0 4 1
A getOptions() 0 4 1
A setDomain() 0 4 1
A connect() 0 11 2
A disconnect() 0 7 1
A assertCorrectResponse() 0 11 3
A handshake() 0 8 4
A setConnectionExtensions() 0 11 4
D command() 0 25 9
A reset() 0 4 1
F send() 42 147 42
A batchSend() 0 5 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Swift often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Swift, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Swift Mailer Core Component.
5
 * Please read the LICENSE file
6
 * @copyright Chris Corbyn <[email protected]>
7
 * @author Chris Corbyn <[email protected]>
8
 * @package Swift
9
 * @version 3.3.2
10
 * @license GNU Lesser General Public License
11
 */
12
13
require_once dirname(__FILE__) . "/Swift/ClassLoader.php";
14
Swift_ClassLoader::load("Swift_LogContainer");
15
Swift_ClassLoader::load("Swift_ConnectionBase");
16
Swift_ClassLoader::load("Swift_BadResponseException");
17
Swift_ClassLoader::load("Swift_Cache");
18
Swift_ClassLoader::load("Swift_CacheFactory");
19
Swift_ClassLoader::load("Swift_Message");
20
Swift_ClassLoader::load("Swift_RecipientList");
21
Swift_ClassLoader::load("Swift_BatchMailer");
22
Swift_ClassLoader::load("Swift_Events");
23
Swift_ClassLoader::load("Swift_Events_Listener");
24
25
/**
26
 * Swift is the central component in the Swift library.
27
 * @package Swift
28
 * @author Chris Corbyn <[email protected]>
29
 * @version 3.3.2
30
 */
31
class Swift
32
{
33
  /**
34
   * The version number.
35
   */
36
  const VERSION = "3.3.2";
37
  /**
38
   * Constant to flag Swift not to try and connect upon instantiation
39
   */
40
  const NO_START = 2;
41
  /**
42
   * Constant to tell Swift not to perform the standard SMTP handshake upon connect
43
   */
44
  const NO_HANDSHAKE = 4;
45
  /**
46
   * Constant to ask Swift to start logging
47
   */
48
  const ENABLE_LOGGING = 8;
49
  /**
50
   * Constant to prevent postConnect() being run in the connection
51
   */
52
  const NO_POST_CONNECT = 16;
53
  /**
54
   * The connection object currently active
55
   * @var Swift_Connection
56
   */
57
  public $connection = null;
58
  /**
59
   * The domain name of this server (should technically be a FQDN)
60
   * @var string
61
   */
62
  protected $domain = null;
63
  /**
64
   * Flags to change the behaviour of Swift
65
   * @var int
66
   */
67
  protected $options;
68
  /**
69
   * Loaded plugins, separated into containers according to roles
70
   * @var array
71
   */
72
  protected $listeners = array();
73
  
74
  /**
75
   * Constructor
76
   * @param Swift_Connection The connection object to deal with I/O
77
   * @param string The domain name of this server (the client) as a FQDN
78
   * @param int Optional flags
79
   * @throws Swift_ConnectionException If a connection cannot be established or the connection is behaving incorrectly
80
   */
81
  public function __construct(Swift_Connection $conn, $domain=false, $options=null)
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
82
  {
83
    $this->initializeEventListenerContainer();
84
    $this->setOptions($options);
85
    
86
    $log = Swift_LogContainer::getLog();
87
    
88
    if ($this->hasOption(self::ENABLE_LOGGING) && !$log->isEnabled())
89
    {
90
      $log->setLogLevel(Swift_Log::LOG_NETWORK);
91
    }
92
    
93
    if (!$domain) $domain = !empty($_SERVER["SERVER_ADDR"]) ? "[" . $_SERVER["SERVER_ADDR"] . "]" : "localhost.localdomain";
94
    
95
    $this->setDomain($domain);
96
    $this->connection = $conn;
97
    
98
    if ($conn && !$this->hasOption(self::NO_START))
99
    {
100
      if ($log->hasLevel(Swift_Log::LOG_EVERYTHING)) $log->add("Trying to connect...", Swift_Log::NORMAL);
101
      $this->connect();
102
    }
103
  }
104
  /**
105
   * Populate the listeners array with the defined listeners ready for plugins
106
   */
107
  protected function initializeEventListenerContainer()
108
  {
109
    Swift_ClassLoader::load("Swift_Events_ListenerMapper");
110
    foreach (Swift_Events_ListenerMapper::getMap() as $interface => $method)
111
    {
112
      if (!isset($this->listeners[$interface]))
113
        $this->listeners[$interface] = array();
114
    }
115
  }
116
  /**
117
   * Add a new plugin to Swift
118
   * Plugins must implement one or more event listeners
119
   * @param Swift_Events_Listener The plugin to load
120
   */
121
  public function attachPlugin(Swift_Events_Listener $plugin, $id)
122
  {
123
    foreach (array_keys($this->listeners) as $key)
124
    {
125
      $listener = "Swift_Events_" . $key;
126
      Swift_ClassLoader::load($listener);
127
      if ($plugin instanceof $listener) $this->listeners[$key][$id] = $plugin;
128
    }
129
  }
130
  /**
131
   * Get an attached plugin if it exists
132
   * @param string The id of the plugin
133
   * @return Swift_Event_Listener
134
   */
135
  public function getPlugin($id)
136
  {
137
    foreach ($this->listeners as $type => $arr)
138
    {
139
      if (isset($arr[$id])) return $this->listeners[$type][$id];
140
    }
141
    return null; //If none found
142
  }
143
  /**
144
   * Remove a plugin attached under the ID of $id
145
   * @param string The ID of the plugin
146
   */
147
  public function removePlugin($id)
148
  {
149
    foreach ($this->listeners as $type => $arr)
150
    {
151
      if (isset($arr[$id]))
152
      {
153
        $this->listeners[$type][$id] = null;
154
        unset($this->listeners[$type][$id]);
155
      }
156
    }
157
  }
158
  /**
159
   * Send a new type of event to all objects which are listening for it
160
   * @param Swift_Events The event to send
161
   * @param string The type of event
162
   * @param string $type
163
   */
164
  public function notifyListeners($e, $type)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $e. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
165
  {
166
    Swift_ClassLoader::load("Swift_Events_ListenerMapper");
167
    if (!empty($this->listeners[$type]) && $notifyMethod = Swift_Events_ListenerMapper::getNotifyMethod($type))
168
    {
169
      $e->setSwift($this);
170
      foreach ($this->listeners[$type] as $k => $listener)
171
      {
172
        $listener->$notifyMethod($e);
173
      }
174
    }
175
    else $e = null;
0 ignored issues
show
Unused Code introduced by
$e is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
176
  }
177
  /**
178
   * Check if an option flag has been set
179
   * @param string Option name
180
   * @param integer $option
181
   * @return boolean
0 ignored issues
show
Documentation introduced by
Should the return type not be integer?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
182
   */
183
  public function hasOption($option)
184
  {
185
    return ($this->options & $option);
186
  }
187
  /**
188
   * Adjust the options flags
189
   * E.g. $obj->setOptions(Swift::NO_START | Swift::NO_HANDSHAKE)
190
   * @param int The bits to set
191
   */
192
  public function setOptions($options)
193
  {
194
    $this->options = (int) $options;
195
  }
196
  /**
197
   * Get the current options set (as bits)
198
   * @return int
199
   */
200
  public function getOptions()
201
  {
202
    return (int) $this->options;
203
  }
204
  /**
205
   * Set the FQDN of this server as it will identify itself
206
   * @param string The FQDN of the server
207
   * @param string|boolean $name
208
   */
209
  public function setDomain($name)
210
  {
211
    $this->domain = (string) $name;
212
  }
213
  /**
214
   * Attempt to establish a connection with the service
215
   * @throws Swift_ConnectionException If the connection cannot be established or behaves oddly
216
   */
217
  public function connect()
218
  {
219
    $this->connection->start();
220
    $greeting = $this->command("", 220);
221
    if (!$this->hasOption(self::NO_HANDSHAKE))
222
    {
223
      $this->handshake($greeting);
0 ignored issues
show
Bug introduced by
It seems like $greeting defined by $this->command('', 220) on line 220 can be null; however, Swift::handshake() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
224
    }
225
    Swift_ClassLoader::load("Swift_Events_ConnectEvent");
226
    $this->notifyListeners(new Swift_Events_ConnectEvent($this->connection), "ConnectListener");
227
  }
228
  /**
229
   * Disconnect from the MTA
230
   * @throws Swift_ConnectionException If the connection will not stop
231
   */
232
  public function disconnect()
233
  {
234
    $this->command("QUIT");
235
    $this->connection->stop();
236
    Swift_ClassLoader::load("Swift_Events_DisconnectEvent");
237
    $this->notifyListeners(new Swift_Events_DisconnectEvent($this->connection), "DisconnectListener");
238
  }
239
  /**
240
   * Throws an exception if the response code wanted does not match the one returned
241
   * @param Swift_Event_ResponseEvent The full response from the service
242
   * @param int The 3 digit response code wanted
243
   * @param integer $codes
244
   * @throws Swift_BadResponseException If the code does not match
245
   */
246
  protected function assertCorrectResponse(Swift_Events_ResponseEvent $response, $codes)
247
  {
248
    $codes = (array)$codes;
249
    if (!in_array($response->getCode(), $codes))
250
    {
251
      $log = Swift_LogContainer::getLog();
252
      $error = "Expected response code(s) [" . implode(", ", $codes) . "] but got response [" . $response->getString() . "]";
253
      if ($log->hasLevel(Swift_Log::LOG_ERRORS)) $log->add($error, Swift_Log::ERROR);
254
      throw new Swift_BadResponseException($error);
255
    }
256
  }
257
  /**
258
   * Have a polite greeting with the server and work out what it's capable of
259
   * @param Swift_Events_ResponseEvent The initial service line respoonse
260
   * @throws Swift_ConnectionException If conversation is not going very well
261
   */
262
  protected function handshake(Swift_Events_ResponseEvent $greeting)
263
  {
264
    if ($this->connection->getRequiresEHLO() || strpos($greeting->getString(), "ESMTP"))
265
      $this->setConnectionExtensions($this->command("EHLO " . $this->domain, 250));
0 ignored issues
show
Bug introduced by
It seems like $this->command('EHLO ' . $this->domain, 250) can be null; however, setConnectionExtensions() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
266
    else $this->command("HELO " . $this->domain, 250);
267
    //Connection might want to do something like authenticate now
268
    if (!$this->hasOption(self::NO_POST_CONNECT)) $this->connection->postConnect($this);
269
  }
270
  /**
271
   * Set the extensions which the service reports in the connection object
272
   * @param Swift_Events_ResponseEvent The list of extensions as reported by the service
273
   */
274
  protected function setConnectionExtensions(Swift_Events_ResponseEvent $list)
275
  {
276
    $le = (strpos($list->getString(), "\r\n") !== false) ? "\r\n" : "\n";
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $le. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
277
    $list = explode($le, $list->getString());
278
    for ($i = 1, $len = count($list); $i < $len; $i++)
279
    {
280
      $extension = substr($list[$i], 4);
281
      $attributes = split("[ =]", $extension);
282
      $this->connection->setExtension($attributes[0], (isset($attributes[1]) ? array_slice($attributes, 1) : array()));
283
    }
284
  }
285
  /**
286
   * Execute a command against the service and get the response
287
   * @param string The command to execute (leave off any CRLF!!!)
288
   * @param int The code to check for in the response, if any. -1 indicates that no response is wanted.
289
   * @param integer $code
0 ignored issues
show
Documentation introduced by
Should the type for parameter $code not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
290
   * @return Swift_Events_ResponseEvent The server's response (could be multiple lines)
0 ignored issues
show
Documentation introduced by
Should the return type not be Swift_Events_ResponseEvent|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
291
   * @throws Swift_ConnectionException If a code was expected but does not match the one returned
292
   */
293
  public function command($command, $code=null)
294
  {
295
    $log = Swift_LogContainer::getLog();
296
    Swift_ClassLoader::load("Swift_Events_CommandEvent");
297
    if ($command !== "")
298
    {
299
      $command_event = new Swift_Events_CommandEvent($command, $code);
300
      $command = null; //For memory reasons
301
      $this->notifyListeners($command_event, "BeforeCommandListener");
302
      if ($log->hasLevel(Swift_Log::LOG_NETWORK) && $code != -1) $log->add($command_event->getString(), Swift_Log::COMMAND);
303
      $end = ($code != -1) ? "\r\n" : null;
304
      $this->connection->write($command_event->getString(), $end);
305
      $this->notifyListeners($command_event, "CommandListener");
306
    }
307
    
308
    if ($code == -1) return null;
309
    
310
    Swift_ClassLoader::load("Swift_Events_ResponseEvent");
311
    $response_event = new Swift_Events_ResponseEvent($this->connection->read());
0 ignored issues
show
Documentation introduced by
$this->connection->read() is of type string, but the function expects a object<The>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
312
    $this->notifyListeners($response_event, "ResponseListener");
313
    if ($log->hasLevel(Swift_Log::LOG_NETWORK)) $log->add($response_event->getString(), Swift_Log::RESPONSE);
314
    if ($command !== "" && $command_event->getCode() !== null)
315
      $this->assertCorrectResponse($response_event, $command_event->getCode());
0 ignored issues
show
Bug introduced by
The variable $command_event does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
316
    return $response_event;
317
  }
318
  /**
319
   * Reset a conversation which has gone badly
320
   * @throws Swift_ConnectionException If the service refuses to reset
321
   */
322
  public function reset()
323
  {
324
    $this->command("RSET", 250);
325
  }
326
  /**
327
   * Send a message to any number of recipients
328
   * @param Swift_Message The message to send.  This does not need to (and shouldn't really) have any of the recipient headers set.
329
   * @param mixed The recipients to send to.  Can be a string, Swift_Address or Swift_RecipientList. Note that all addresses apart from Bcc recipients will appear in the message headers
330
   * @param mixed The address to send the message from.  Can either be a string or an instance of Swift_Address.
331
   * @return int The number of successful recipients
332
   * @throws Swift_ConnectionException If sending fails for any reason.
333
   */
334
  public function send(Swift_Message $message, $recipients, $from)
335
  {
336
    Swift_ClassLoader::load("Swift_Message_Encoder");
337 View Code Duplication
    if (is_string($recipients) && preg_match("/^" . Swift_Message_Encoder::CHEAP_ADDRESS_RE . "\$/", $recipients))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
338
    {
339
      $recipients = new Swift_Address($recipients);
340
    }
341
    elseif (!($recipients instanceof Swift_AddressContainer))
342
      throw new Exception("The recipients parameter must either be a valid string email address, ".
343
      "an instance of Swift_RecipientList or an instance of Swift_Address.");
344
      
345 View Code Duplication
    if (is_string($from) && preg_match("/^" . Swift_Message_Encoder::CHEAP_ADDRESS_RE . "\$/", $from))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
346
    {
347
      $from = new Swift_Address($from);
348
    }
349
    elseif (!($from instanceof Swift_Address))
350
      throw new Exception("The sender parameter must either be a valid string email address or ".
351
      "an instance of Swift_Address.");
352
    
353
    $log = Swift_LogContainer::getLog();
354
    
355
    if (!$message->getEncoding() && !$this->connection->hasExtension("8BITMIME"))
0 ignored issues
show
Bug Best Practice introduced by
The expression $message->getEncoding() of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
356
    {
357
      $message->setEncoding("QP", true, true);
358
    }
359
    
360
    $list = $recipients;
361
    if ($recipients instanceof Swift_Address)
362
    {
363
      $list = new Swift_RecipientList();
364
      $list->addTo($recipients);
365
    }
366
    
367
    Swift_ClassLoader::load("Swift_Events_SendEvent");
368
    $send_event = new Swift_Events_SendEvent($message, $list, $from, 0);
0 ignored issues
show
Compatibility introduced by
$list of type object<Swift_AddressContainer> is not a sub-type of object<Swift_RecipientList>. It seems like you assume a child class of the class Swift_AddressContainer to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
369
    
370
    $this->notifyListeners($send_event, "BeforeSendListener");
371
    
372
    $to = $cc = array();
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $to. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
Comprehensibility introduced by
Avoid variables with short names like $cc. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
373
    if (!($has_from = $message->getFrom())) $message->setFrom($from);
374
    if (!($has_return_path = $message->getReturnPath())) $message->setReturnPath($from->build(true));
375
    if (!($has_reply_to = $message->getReplyTo())) $message->setReplyTo($from);
376
    if (!($has_message_id = $message->getId())) $message->generateId();
377
    
378
    $this->command("MAIL FROM: " . $message->getReturnPath(true), 250);
379
    
380
    $failed = 0;
381
    $sent = 0;
382
    $tmp_sent = 0;
383
    
384
    $it = $list->getIterator("to");
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $it. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
385 View Code Duplication
    while ($it->hasNext())
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
386
    {
387
      $it->next();
388
      $address = $it->getValue();
389
      $to[] = $address->build();
390
      try {
391
        $this->command("RCPT TO: " . $address->build(true), 250);
392
        $tmp_sent++;
393
      } catch (Swift_BadResponseException $e) {
394
        $failed++;
395
        $send_event->addFailedRecipient($address->getAddress());
396
        if ($log->hasLevel(Swift_Log::LOG_FAILURES)) $log->addfailedRecipient($address->getAddress());
397
      }
398
    }
399
    $it = $list->getIterator("cc");
400 View Code Duplication
    while ($it->hasNext())
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
401
    {
402
      $it->next();
403
      $address = $it->getValue();
404
      $cc[] = $address->build();
405
      try {
406
        $this->command("RCPT TO: " . $address->build(true), 250);
407
        $tmp_sent++;
408
      } catch (Swift_BadResponseException $e) {
409
        $failed++;
410
        $send_event->addFailedRecipient($address->getAddress());
411
        if ($log->hasLevel(Swift_Log::LOG_FAILURES)) $log->addfailedRecipient($address->getAddress());
412
      }
413
    }
414
    
415
    if ($failed == (count($to) + count($cc)))
416
    {
417
      $this->reset();
418
      $this->notifyListeners($send_event, "SendListener");
419
      return 0;
420
    }
421
    
422
    if (!($has_to = $message->getTo()) && !empty($to)) $message->setTo($to);
423
    if (!($has_cc = $message->getCc()) && !empty($cc)) $message->setCc($cc);
424
    
425
    $this->command("DATA", 354);
426
    $data = $message->build();
427
    
428
    while (false !== $bytes = $data->read())
429
      $this->command($bytes, -1);
430
    if ($log->hasLevel(Swift_Log::LOG_NETWORK)) $log->add("<MESSAGE DATA>", Swift_Log::COMMAND);
431
    try {
432
      $this->command("\r\n.", 250);
433
      $sent += $tmp_sent;
434
    } catch (Swift_BadResponseException $e) {
435
      $failed += $tmp_sent;
436
    }
437
    
438
    $tmp_sent = 0;
0 ignored issues
show
Unused Code introduced by
$tmp_sent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
439
    $has_bcc = $message->getBcc();
440
    $it = $list->getIterator("bcc");
441
    while ($it->hasNext())
442
    {
443
      $it->next();
444
      $address = $it->getValue();
445
      if (!$has_bcc) $message->setBcc($address->build());
446
      try {
447
        $this->command("MAIL FROM: " . $message->getReturnPath(true), 250);
448
        $this->command("RCPT TO: " . $address->build(true), 250);
449
        $this->command("DATA", 354);
450
        $data = $message->build();
451
        while (false !== $bytes = $data->read())
452
          $this->command($bytes, -1);
453
        if ($log->hasLevel(Swift_Log::LOG_NETWORK)) $log->add("<MESSAGE DATA>", Swift_Log::COMMAND);
454
        $this->command("\r\n.", 250);
455
        $sent++;
456
      } catch (Swift_BadResponseException $e) {
457
        $failed++;
458
        $send_event->addFailedRecipient($address->getAddress());
459
        if ($log->hasLevel(Swift_Log::LOG_FAILURES)) $log->addfailedRecipient($address->getAddress());
460
        $this->reset();
461
      }
462
    }
463
    
464
    $total = count($to) + count($cc) + count($list->getBcc());
465
    
466
    $send_event->setNumSent($sent);
467
    $this->notifyListeners($send_event, "SendListener");
468
    
469
    if (!$has_return_path) $message->setReturnPath("");
0 ignored issues
show
Bug Best Practice introduced by
The expression $has_return_path of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
470
    if (!$has_from) $message->setFrom("");
0 ignored issues
show
Bug Best Practice introduced by
The expression $has_from of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
471
    if (!$has_to) $message->setTo("");
472
    if (!$has_reply_to) $message->setReplyTo(null);
473
    if (!$has_cc) $message->setCc(null);
474
    if (!$has_bcc) $message->setBcc(null);
475
    if (!$has_message_id) $message->setId(null);
0 ignored issues
show
Bug Best Practice introduced by
The expression $has_message_id of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
476
    
477
    if ($log->hasLevel(Swift_Log::LOG_NETWORK)) $log->add("Message sent to " . $sent . "/" . $total . " recipients", Swift_Log::NORMAL);
478
    
479
    return $sent;
480
  }
481
  /**
482
   * Send a message to a batch of recipients.
483
   * Unlike send() this method ignores Cc and Bcc recipients and does not reveal every recipients' address in the headers
484
   * @param Swift_Message The message to send (leave out the recipient headers unless you are deliberately overriding them)
485
   * @param Swift_RecipientList The addresses to send to
486
   * @param Swift_Address The address the mail is from (sender)
487
   * @param Swift_Address $from
488
   * @return int The number of successful recipients
489
   */
490
  public function batchSend(Swift_Message $message, Swift_RecipientList $to, $from)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $to. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
491
  {
492
    $batch = new Swift_BatchMailer($this);
493
    return $batch->send($message, $to, $from);
494
  }
495
}
496