Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
Attachment
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
4 / 4
5
100.00% covered (success)
100.00%
1 / 1
 create
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 createFromContent
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getFilename
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
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <dev@noladev.com>
8 * @copyright  Copyright (c) 2009-2027 NOLA Interactive, LLC.
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12namespace Pop\Mail\Message;
13
14use Pop\Mime\Part;
15
16/**
17 * Attachment message part class
18 *
19 * @category   Pop
20 * @package    Pop\Mail
21 * @author     Nick Sagona, III <dev@noladev.com>
22 * @copyright  Copyright (c) 2009-2027 NOLA Interactive, LLC.
23 * @license    https://www.popphp.org/license     New BSD License
24 * @version    5.0.0
25 */
26class Attachment extends Part
27{
28    use CharsetAwareTrait;
29    use PartContentTrait;
30
31    /**
32     * The original on-disk path this attachment was created from, if any.
33     * Deliberately diverges from parent::getFilename() (which returns the
34     * basename, decoded from headers) - three transports need the real
35     * openable path for curl_file_create().
36     * @var ?string
37     */
38    protected ?string $sourcePath = null;
39
40    public static function create(
41        string $file, ?string $contentType = null, string $disposition = 'attachment',
42        Part\Body\Encoding $encoding = Part\Body\Encoding::BASE64, int|bool $split = true
43    ): static
44    {
45        if (!file_exists($file)) {
46            throw new Exception("Error: The file '" . $file . "' does not exist.");
47        }
48        $attachment = parent::attachment($file, $contentType, $disposition, $encoding, $split);
49        $attachment->sourcePath = $file;
50        $attachment->addHeader('Content-Description', basename($file));
51        return $attachment;
52    }
53
54    public static function createFromContent(
55        string $content, string $filename, ?string $contentType = null, string $disposition = 'attachment',
56        Part\Body\Encoding $encoding = Part\Body\Encoding::BASE64, int|bool $split = true
57    ): static
58    {
59        $attachment = parent::attachmentFromContent($content, $filename, $contentType, $disposition, $encoding, $split);
60        $attachment->addHeader('Content-Description', basename($filename));
61        return $attachment;
62    }
63
64    /**
65     * Get the real on-disk path this attachment was created from.
66     *
67     * No fallback to parent::getFilename() is used deliberately. The parent method
68     * returns a basename decoded from headers; Part::attachmentFromContent() marks
69     * the body as file-like and unconditionally sets a Content-Disposition filename=
70     * parameter. A fallback would return a fabricated basename (e.g. 'generated.txt')
71     * instead of null for in-memory attachments created via createFromContent().
72     * This method guarantees null for in-memory attachments to honor that contract.
73     *
74     * @return ?string The real path if created from a file, null if in-memory
75     */
76    public function getFilename(): ?string
77    {
78        return $this->sourcePath;
79    }
80
81    public function getBasename(): ?string
82    {
83        return parent::getFilename();
84    }
85
86}