Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
Attachment
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
5 / 5
24
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
1 / 1
20
 createFromFile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createFromStream
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBasename
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStream
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Mail\Message;
15
16/**
17 * Attachment message part class
18 *
19 * @category   Pop
20 * @package    Pop\Mail
21 * @author     Nick Sagona, III <dev@nolainteractive.com>
22 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com)
23 * @license    http://www.popphp.org/license     New BSD License
24 * @version    3.6.0
25 */
26class Attachment extends AbstractPart
27{
28
29    /**
30     * File attachment basename
31     * @var string
32     */
33    protected $basename = null;
34
35    /**
36     * File attachment original stream content
37     * @var string
38     */
39    protected $stream = null;
40
41    /**
42     * Common content types for auto-detection
43     * @var array
44     */
45    protected $contentTypes = [
46        'csv'    => 'text/csv',
47        'doc'    => 'application/msword',
48        'docx'   => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
49        'gif'    => 'image/gif',
50        'html'   => 'text/html',
51        'htm'    => 'text/html',
52        'jpe'    => 'image/jpeg',
53        'jpg'    => 'image/jpeg',
54        'jpeg'   => 'image/jpeg',
55        'log'    => 'text/plain',
56        'md'     => 'text/plain',
57        'pdf'    => 'application/pdf',
58        'png'    => 'image/png',
59        'ppt'    => 'application/vnd.ms-powerpoint',
60        'pptx'   => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
61        'svg'    => 'image/svg+xml',
62        'tif'    => 'image/tiff',
63        'tiff'   => 'image/tiff',
64        'tsv'    => 'text/tsv',
65        'txt'    => 'text/plain',
66        'xls'    => 'application/vnd.ms-excel',
67        'xlsx'   => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
68        'zip'    => 'application/x-zip'
69    ];
70
71    /**
72     * Constructor
73     *
74     * Instantiate the mail attachment object
75     *
76     * @param  string  $file
77     * @param  string  $stream
78     * @param  array   $options  ['contentType', 'basename', 'encoding', 'chunk']
79     * @throws Exception
80     */
81    public function __construct($file = null, $stream = null, array $options = [])
82    {
83        if (null !== $stream) {
84            $this->stream   = $stream;
85            $this->basename = $options['basename'] ?? 'file.tmp';
86        } else if (null !== $file) {
87            if (!file_exists($file)) {
88                throw new Exception("Error: The file '" . $file . "' does not exist.");
89            } else {
90                $this->stream   = file_get_contents($file);
91                $this->basename = basename($file);
92            }
93        }
94
95        $chunk       = (isset($options['chunk'])) ? (bool)$options['chunk'] : false;
96        $contentType = null;
97        $encoding    = null;
98
99        // Set encoding
100        if (isset($options['encoding'])) {
101            switch (strtoupper($options['encoding'])) {
102                case self::BASE64:
103                case self::QUOTED_PRINTABLE:
104                case self::BINARY:
105                case self::_8BIT:
106                case self::_7BIT:
107                    $encoding = strtoupper($options['encoding']);
108            }
109        }
110
111        // Set content type
112        foreach ($options as $key => $value) {
113            $key = strtolower($key);
114            if (($key == 'content-type') || ($key == 'contenttype') ||
115                ($key == 'mime-type') || ($key == 'mimetype') || ($key == 'mime')) {
116                $contentType = $value;
117            }
118        }
119
120        // Fallback content type detection
121        if ((null === $contentType) && (strpos($this->basename, '.') !== false)) {
122            $pathInfo    = pathinfo($this->basename);
123            $ext         = strtolower($pathInfo['extension']);
124            $contentType = (array_key_exists($ext, $this->contentTypes)) ?
125                $this->contentTypes[$ext] : 'application/octet-stream';
126        }
127
128        parent::__construct($this->stream, $contentType . '; name="' . $this->basename . '"', $encoding, $chunk);
129
130        $this->addHeader('Content-Description', $this->basename)
131             ->addHeader('Content-Disposition', 'attachment; filename="' . $this->basename . '"')
132             ->setCharSet(null);
133    }
134
135    /**
136     * Create attachment from file
137     *
138     * @param  string  $file
139     * @param  array   $options  ['contentType', 'basename', 'encoding', 'chunk']
140     * @return self
141     */
142    public static function createFromFile($file, array $options = [])
143    {
144        return new self($file, null, $options);
145    }
146
147    /**
148     * Create attachment from stream
149     *
150     * @param  string  $stream
151     * @param  array   $options  ['contentType', 'basename', 'encoding', 'chunk']
152     * @return self
153     */
154    public static function createFromStream($stream, array $options = [])
155    {
156        return new self(null, $stream, $options);
157    }
158
159    /**
160     * Get attachment basename
161     *
162     * @return string
163     */
164    public function getBasename()
165    {
166        return $this->basename;
167    }
168
169    /**
170     * Get attachment original stream content
171     *
172     * @return string
173     */
174    public function getStream()
175    {
176        return $this->stream;
177    }
178
179}