Completed
Push — master ( 6cff59...6e5f78 )
by Rudie
01:30
created

IMAPMessage::headerString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace rdx\imap;
4
5
class IMAPMessage extends IMAPMessageContent implements IMAPMessagePartInterface {
6
7
	/** @var IMAPMailbox */
8
	protected $mailbox;
9
10
	/** @var int */
11
	protected $msgNumber = 1; // Body starts at 1. Header is 0.
12
13
	/** @var bool */
14
	protected $unseen = true;
15
16
	/** @var string[]  */
17
	protected $headers = [];
18
19
	/** @var string */
20
	protected $subject = '';
21
22
	/** @var string */
23
	protected $subtype = '';
24
25
	public function __construct( IMAPMailbox $mailbox, $msgNumber, $unseen = null ) {
26
		$this->mailbox = $mailbox;
27
		$this->msgNumber = $msgNumber;
28
		$this->unseen = $unseen;
29
30
		if ( $unseen === null ) {
31
			$this->unseen = (bool) trim($this->header('unseen'));
32
		}
33
	}
34
35
	/** @return bool|bool[] */
36
	protected function flags( $flags, $clear ) {
37
		$cb = [$this->mailbox()->imap(), $clear ? 'unflag' : 'flag'];
38
39
		$feedback = [];
40
		foreach ( (array) $flags AS $flag ) {
41
			$flag = '\\' . ucfirst($flag);
42
			$feedback[] = call_user_func($cb, $this->msgNumber, $flag);
43
		}
44
45
		return is_array($flags) ? $feedback : $feedback[0];
46
	}
47
48
	/** @return bool|bool[] */
49
	public function flag( $flags ) {
50
		return $this->flags($flags, false);
51
	}
52
53
	/** @return bool|bool[] */
54
	public function unflag( $flags ) {
55
		return $this->flags($flags, true);
56
	}
57
58
	/** @return int */
59
	public function utc() {
60
		return strtotime($this->header('date'));
61
	}
62
63
	/** @return string */
64
	public function subject() {
65
		if ( empty($this->subject) ) {
66
			$subject = $this->mailbox()->imap()->utf8($this->header('subject'));
67
			$this->subject = trim($subject);
68
		}
69
70
		return $this->subject;
71
	}
72
73
	/** @return string */
74
	public function headerString() {
75
		return trim($this->mailbox()->imap()->fetchheader($this->msgNumber()));
76
	}
77
78
	/** @return IMAPMessagePart */
79
	public function createMessagePart( $structure, $section ) {
80
		return new IMAPMessagePart($this, $structure, $section);
81
	}
82
83
	/** @return IMAPMessagePart[] */
84
	public function parts() {
85
		if ( empty($this->parts) ) {
86
			$structure = $this->structure();
87
88
			// Possibilities:
89
			// - PLAIN
90
			// - ALTERNATIVE
91
			// - MIXED
92
			// - DELIVERY-STATUS
93
			// - RFC822
94
			// - REPORT
95
			// - HTML
96
			// - CALENDAR
97
			// - JPEG
98
99
			if ( empty($structure->parts) ) {
100
				$this->parts[] = $this->createMessagePart(
101
					$structure,
102
					[1]
103
				);
104
			}
105
			else {
106
				foreach ( $structure->parts as $n => $part ) {
107
					$this->parts[] = $this->createMessagePart(
108
						$part,
109
						[$n + 1]
110
					);
111
				}
112
			}
113
		}
114
115
		return $this->parts;
116
	}
117
118
	/** @return object */
119
	public function structure() {
120
		if ( empty($this->structure) ) {
121
			$this->structure = $this->mailbox()->imap()->fetchstructure($this->msgNumber);
122
		}
123
124
		return $this->structure;
125
	}
126
127
	/** @return string */
128
	public function subtype() {
129
		if ( empty($this->subtype) ) {
130
			$structure = $this->structure();
131
			$this->subtype = @$structure->subtype ?: '';
132
		}
133
134
		return $this->subtype;
135
	}
136
137
	/** @return int[] */
138
	public function section() {
139
		return [];
140
	}
141
142
	/** @return string */
143
	public function content() {
144
		if ( count($this->parts()) == 1 ) {
145
			return $this->part(0)->content();
146
		}
147
148
		return '';
149
	}
150
151
	/** @return string */
152
	public function decodedContent() {
153
		if ( count($this->parts()) == 1 ) {
154
			return $this->part(0)->decodedContent();
155
		}
156
157
		return '';
158
	}
159
160
	/** @return bool */
161
	public function delete() {
162
		return $this->mailbox()->imap()->delete($this->msgNumber);
163
	}
164
165
	/** @return string[] */
166
	public function simpleStructure() {
167
		$parts = [];
168
		foreach ( $this->allParts() as $part ) {
169
			$name = '';
170
171
			$name .= implode('.', $part->section()) . '. ';
172
			if ( $part->parts() ) {
173
				$name .= '*';
174
			}
175
			$name .= $part->subtype();
176
			if ( $part->parameter('disposition') ) {
177
				if ( $filename = $part->filename() ) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface rdx\imap\IMAPMessagePartInterface as the method filename() does only exist in the following implementations of said interface: rdx\imap\IMAPMessagePart.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
178
					$name .= ' (' . $filename . ')';
179
				}
180
			}
181
			if ( $bytes = $part->parameter('bytes') ) {
182
				$name .= ' (' . number_format($bytes/1024, 1) . 'kb)';
183
			}
184
185
			$parts[] = $name;
186
		}
187
188
		return $parts;
189
	}
190
191
	/** @return int */
192
	public function msgNumber() {
193
		return $this->msgNumber;
194
	}
195
196
	/** @return IMAPMailbox */
197
	public function mailbox() {
198
		return $this->mailbox;
199
	}
200
201
}
202