Completed
Pull Request — master (#33)
by
unknown
11:47
created

EmbeddingImages::attach()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: gilbert
5
 * Date: 21/10/16
6
 * Time: 14:05
7
 */
8
9
namespace MtMail\ComposerPlugin;
10
11
use MtMail\Event\ComposerEvent;
12
use Zend\EventManager\AbstractListenerAggregate;
13
use Zend\EventManager\EventManagerInterface;
14
use Zend\Mime\Part as MimePart;
15
use Zend\Mime\Mime;
16
use Zend\Mime\Message as MimeMessage;
17
use Zend\Mime\Part;
18
19
class EmbeddingImages extends AbstractListenerAggregate implements PluginInterface
20
{
21
    public function addImages(ComposerEvent $event)
0 ignored issues
show
Coding Style introduced by
addImages 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...
22
    {
23
        $parts = $event->getBody()->getParts();
24
25
        $htmlBody = null;
26
        $htmlPart = null;
0 ignored issues
show
Unused Code introduced by
$htmlPart 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...
27
        $textBody = null;
28
29
        // locate HTML body
30
        foreach ($parts as $part) {
31
            foreach ($part->getHeadersArray() as $header) {
32
                if ($header[0] == 'Content-Type' && strpos($header[1], 'text/html') === 0) {
33
                    $htmlPart = $part;
0 ignored issues
show
Unused Code introduced by
$htmlPart 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...
34
                    $htmlBody = $part->getRawContent();
35
                } elseif ($header[0] == 'Content-Type' && strpos($header[1], 'text/plain') === 0) {
36
                    $textBody = $part->getRawContent();
37
                }
38
            }
39
        }
40
41
        if (!$htmlBody) {
42
            // can only work if HTML body exists
43
            return;
44
        }
45
46
        $doc = new \DOMDocument();
47
        $doc->loadHTML($htmlBody);
48
        $elements = $doc->getElementsByTagName('img');
49
        $elements =  (array) $elements;
50
51
        if (count($elements ) > 0) {
52
            $attachement = [];
53
            foreach ($elements as $key => $element) {
54
                // traitement du nom de fichiers pour apprécier le contexte
55
                $file = $element->getAttribute("src");
56
                $filename = $file;
57
                $pos = strpos($file , "~");
0 ignored issues
show
Coding Style introduced by
Space found before comma in function call
Loading history...
58
                if ($pos !== false) {
59
                    $finUser = strpos($file , "/", $pos);
0 ignored issues
show
Coding Style introduced by
Space found before comma in function call
Loading history...
60
                    $filename = $_SERVER["CONTEXT_DOCUMENT_ROOT"].substr($file, $finUser);
61
                } else {
62
                    $pos = strpos($file, $_SERVER['HTTP_HOST']);
63
                    if ($pos !== false) {
64
                        $filename = $_SERVER["DOCUMENT_ROOT"].substr($file, $pos + strlen($_SERVER['HTTP_HOST']));
65
                    }
66
                }
67
                if (is_readable($filename)) {
68
                    $at = new MimePart(file_get_contents($filename));
69
                    $at->type = $this->mimeByExtension($filename);
70
                    $at->disposition = Mime::DISPOSITION_INLINE;
71
                    $at->encoding = Mime::ENCODING_BASE64;
72
                    $at->id = 'cid_' . md5_file($filename);
73
                    $htmlBody = str_replace($file, 'cid:' . $at->id, $htmlBody);
74
                    $attachement[] = $at;
75
                }
76
            }
77
78
            if (sizeof($attachement) > 0) {
79
                $textPart           = new MimePart($textBody);
80
                $textPart->encoding = Mime::ENCODING_QUOTEDPRINTABLE;
81
                $textPart->type     = "text/plain; charset=UTF-8";
82
83
                $htmlPart           = new MimePart($htmlBody);
84
                $htmlPart->encoding = Mime::ENCODING_QUOTEDPRINTABLE;
85
                $htmlPart->type     = "text/html; charset=UTF-8";
86
87
                $content = new MimeMessage();
88
                $content->addPart($textPart);
89
                $content->addPart($htmlPart);
90
91
                $contentPart = new Part($content->generateMessage());
92
                $contentPart->type = "multipart/alternative;\n boundary=\"" . $content->getMime()->boundary() . '"';
93
94
                $event->getBody()->setParts([$contentPart]);
95
96
                foreach ($attachement as $at) {
97
                    $event->getBody()->addPart($at);
98
                }
99
100
                // force multipart/alternative content type
101
                $event->getMessage()->getHeaders()->get('content-type')->setType('multipart/related')
102
                    ->addParameter('boundary', $event->getBody()->getMime()->boundary());
103
            }
104
        }
105
    }
106
107
    private function mimeByExtension($filename)
108
    {
109
        if (is_readable($filename) ) {
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces before closing bracket; 1 found
Loading history...
110
            $extension = pathinfo($filename, PATHINFO_EXTENSION);
111
            switch ($extension) {
112
                case 'gif':
113
                    $type = 'image/gif';
114
                    break;
115
                case 'jpg':
116
                case 'jpeg':
117
                    $type = 'image/jpg';
118
                    break;
119
                case 'png':
120
                    $type = 'image/png';
121
                    break;
122
                default:
123
                    $type = 'application/octet-stream';
124
            }
125
        }
126
127
        return $type;
0 ignored issues
show
Bug introduced by
The variable $type 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...
128
    }
129
130
    public function attach(EventManagerInterface $events, $priority = 2)
131
    {
132
        $this->listeners[] = $events->attach(ComposerEvent::EVENT_COMPOSE_POST, [$this, 'addImages']);
133
    }
134
}
135