Passed
Branch master (6f17b7)
by Daniel
03:55
created

Mail   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 442
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 442
rs 8.4864
c 0
b 0
f 0
wmc 48

27 Methods

Rating   Name   Duplication   Size   Complexity  
A getInternalDate() 0 3 1
A getPlainTextBody() 0 5 2
A getFromEmail() 0 7 2
A load() 0 5 1
A __construct() 0 20 3
B formatEmailList() 0 26 5
A getThreatId() 0 3 1
A getSubject() 0 3 1
A getDeliveredTo() 0 3 1
A getAttachmentsWithData() 0 3 1
A getRawPlainTextBody() 0 3 1
A getLabels() 0 3 1
A getId() 0 3 1
A buildHeaders() 0 16 2
A getBody() 0 6 1
A getHeaders() 0 3 1
A getHtmlBody() 0 5 2
A getTo() 0 5 1
A getRawHtmlBody() 0 3 1
A getDate() 0 3 1
A hasAttachments() 0 15 3
A getFromName() 0 7 1
B getAttachments() 0 23 4
A getSize() 0 3 1
A getFrom() 0 11 2
B getBodyPart() 0 21 6
A using() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Mail 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.

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 Mail, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Dacastro4\LaravelGmail\Services\Message;
4
5
use Carbon\Carbon;
6
use Dacastro4\LaravelGmail\GmailConnection;
7
use Dacastro4\LaravelGmail\Traits\HasDecodableBody;
8
use Dacastro4\LaravelGmail\Traits\Modifiable;
9
use Dacastro4\LaravelGmail\Traits\Replyable;
10
use Google_Service_Gmail;
11
use Illuminate\Support\Collection;
12
13
/**
14
 * Class SingleMessage
15
 * @package Dacastro4\LaravelGmail\services
16
 */
17
class Mail extends GmailConnection
18
{
19
	use HasDecodableBody,
0 ignored issues
show
Bug introduced by
The trait Dacastro4\LaravelGmail\Traits\Modifiable requires the property $users_messages which is not provided by Dacastro4\LaravelGmail\Services\Message\Mail.
Loading history...
Bug introduced by
The trait Dacastro4\LaravelGmail\Traits\Replyable requires the property $users_messages which is not provided by Dacastro4\LaravelGmail\Services\Message\Mail.
Loading history...
20
		Modifiable,
21
		Replyable {
22
		Replyable::__construct as private __rConstruct;
23
		Modifiable::__construct as private __mConstruct;
24
	}
25
26
	/**
27
	 * @var
28
	 */
29
	public $id;
30
31
	/**
32
	 * @var
33
	 */
34
	public $internalDate;
35
36
	/**
37
	 * @var
38
	 */
39
	public $labels;
40
41
	/**
42
	 * @var
43
	 */
44
	public $size;
45
46
	/**
47
	 * @var
48
	 */
49
	public $threatId;
50
51
	/**
52
	 * @var \Google_Service_Gmail_MessagePart
53
	 */
54
	public $payload;
55
56
	/**
57
	 * @var Google_Service_Gmail
58
	 */
59
	public $service;
60
61
	/**
62
	 * SingleMessage constructor.
63
	 *
64
	 * @param \Google_Service_Gmail_Message $message
65
	 * @param bool $preload
66
	 *
67
	 */
68
	public function __construct( \Google_Service_Gmail_Message $message = null, $preload = false )
69
	{
70
71
		$this->service = new Google_Service_Gmail( $this );
72
73
		$this->__rConstruct();
74
		$this->__mConstruct();
75
		parent::__construct( config() );
0 ignored issues
show
Unused Code introduced by
The call to Dacastro4\LaravelGmail\T...difiable::__construct() has too many arguments starting with config(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

75
		parent::/** @scrutinizer ignore-call */ 
76
          __construct( config() );

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
76
77
		if ( ! is_null( $message ) ) {
78
			if ( $preload ) {
79
				$message = $this->service->users_messages->get( 'me', $message->getId() );
80
			}
81
82
			$this->id = $message->getId();
83
			$this->internalDate = $message->getInternalDate();
84
			$this->labels = $message->getLabelIds();
85
			$this->size = $message->getSizeEstimate();
86
			$this->threatId = $message->getThreadId();
87
			$this->payload = $message->getPayload();
88
		}
89
	}
90
91
	/**
92
	 * Returns ID of the email
93
	 *
94
	 * @return string
95
	 */
96
	public function getId()
97
	{
98
		return $this->id;
99
	}
100
101
	/**
102
	 * Return a UNIX version of the date
103
	 *
104
	 * @return int UNIX date
105
	 */
106
	public function getInternalDate()
107
	{
108
		return $this->internalDate;
109
	}
110
111
	/**
112
	 * Returns the labels of the email
113
	 * Example: INBOX, STARRED, UNREAD
114
	 *
115
	 * @return array
116
	 */
117
	public function getLabels()
118
	{
119
		return $this->labels;
120
	}
121
122
	/**
123
	 * Returns approximate size of the email
124
	 *
125
	 * @return mixed
126
	 */
127
	public function getSize()
128
	{
129
		return $this->size;
130
	}
131
132
	/**
133
	 * Returns threat ID of the email
134
	 *
135
	 * @return string
136
	 */
137
	public function getThreatId()
138
	{
139
		return $this->threatId;
140
	}
141
142
	/**
143
	 * Returns all the headers of the email
144
	 *
145
	 * @return Collection
146
	 */
147
	public function getHeaders()
148
	{
149
		return $this->buildHeaders( $this->payload->getHeaders() );
150
	}
151
152
	/**
153
	 * Returns the subject of the email
154
	 *
155
	 * @return string
156
	 */
157
	public function getSubject()
158
	{
159
		return $this->getHeader( 'Subject' );
160
	}
161
162
	/**
163
	 * Returns array of name and email of each recipient
164
	 *
165
	 * @return array
166
	 */
167
	public function getFrom()
168
	{
169
		$from = $this->getHeader( 'From' );
170
171
		preg_match( '/<(.*)>/', $from, $matches );
172
173
		$name = preg_replace( '/ <(.*)>/', '', $from );
174
175
		return [
176
			'name'  => $name,
177
			'email' => isset( $matches[ 1 ] ) ? $matches[ 1 ] : null,
178
		];
179
	}
180
181
	/**
182
	 * Returns email of sender
183
	 *
184
	 * @return string|null
185
	 */
186
	public function getFromEmail()
187
	{
188
		$from = $this->getHeader( 'From' );
189
190
		preg_match( '/<(.*)>/', $from, $matches );
191
192
		return isset( $matches[ 1 ] ) ? $matches[ 1 ] : null;
193
	}
194
195
	/**
196
	 * Returns name of the sender
197
	 *
198
	 * @return string|null
199
	 */
200
	public function getFromName()
201
	{
202
		$from = $this->getHeader( 'From' );
203
204
		$name = preg_replace( '/ <(.*)>/', '', $from );
205
206
		return $name;
207
	}
208
209
	/**
210
	 * Returns array list of recipients
211
	 *
212
	 * @return array
213
	 */
214
	public function getTo()
215
	{
216
		$allTo = $this->getHeader( 'To' );
217
218
		return $this->formatEmailList( $allTo );
219
	}
220
221
	/**
222
	 * Returns the original date that the email was sent
223
	 *
224
	 * @return Carbon
225
	 */
226
	public function getDate()
227
	{
228
		return Carbon::parse( $this->getHeader( 'Date' ) );
229
	}
230
231
	/**
232
	 * Returns email of the original recipient
233
	 *
234
	 * @return string
235
	 */
236
	public function getDeliveredTo()
237
	{
238
		return $this->getHeader( 'Delivered-To' );
239
	}
240
241
	/**
242
	 * @param bool $raw
243
	 *
244
	 * @return string
245
	 */
246
	public function getPlainTextBody( $raw = false )
247
	{
248
		$content = $this->getBody();
249
250
		return $raw ? $content : $this->getDecodedBody( $content );
251
	}
252
253
	/**
254
	 * @return string base64 version of the body
255
	 */
256
	public function getRawPlainTextBody()
257
	{
258
		return $this->getPlainTextBody( true );
259
	}
260
261
	/**
262
	 * @param bool $raw
263
	 *
264
	 * @return string
265
	 */
266
	public function getHtmlBody( $raw = false )
267
	{
268
		$content = $this->getBody( 'text/html' );
269
270
		return $raw ? $content : $this->getDecodedBody( $content );
271
	}
272
273
	/**
274
	 * @return string base64 version of the body
275
	 */
276
	public function getRawHtmlBody()
277
	{
278
		return $this->getHtmlBody( true );
279
	}
280
281
	/**
282
	 * Returns a collection of attachments
283
	 *
284
	 * @param bool $preload Preload the attachment's data
285
	 *
286
	 * @return Collection
287
	 * @throws \Exception
288
	 */
289
	public function getAttachments( $preload = false )
290
	{
291
		$attachments = new Collection( [] );
292
		$parts = $this->payload->getParts();
293
294
		/** @var \Google_Service_Gmail_MessagePart $part */
295
		foreach ( $parts as $part ) {
296
297
			$body = $part->getBody();
298
299
			if ( $body->getAttachmentId() ) {
300
				$attachment = ( new Attachment( $this->getId(), $part ) );
301
				if ( $preload ) {
302
					$attachment = $attachment->getData();
303
				}
304
				$attachments->push(
305
					$attachment
306
				);
307
			}
308
309
		}
310
311
		return $attachments;
312
313
	}
314
315
	/**
316
	 * @return Collection
317
	 * @throws \Exception
318
	 */
319
	public function getAttachmentsWithData()
320
	{
321
		return $this->getAttachments( true );
322
	}
323
324
	/**
325
	 * @return boolean
326
	 */
327
	public function hasAttachments()
328
	{
329
		$attachments = 0;
330
		$parts = $this->payload->getParts();
331
332
		/**  @var \Google_Service_Gmail_MessagePart $part */
333
		foreach ( $parts as $part ) {
334
			$body = $part->getBody();
335
			if ( $body->getAttachmentId() ) {
336
				$attachments ++;
337
				break;
338
			}
339
		}
340
341
		return ! ! $attachments;
342
	}
343
344
	/**
345
	 * @param string $type
346
	 *
347
	 * @return \Google_Service_Gmail_MessagePart|null
348
	 */
349
	private function getBodyPart( $type = 'text/plain' )
350
	{
351
352
		$body = $this->payload->getParts();
353
354
		if ( $this->hasAttachments() ) {
355
			//Get the first attachment that is the main body
356
			$body = isset( $body[ 0 ] ) ? $body[ 0 ] : [];
357
			$parts = $body->getParts();
358
		} else {
359
			$parts = $body;
360
		}
361
362
		/** @var \Google_Service_Gmail_MessagePart $part */
363
		foreach ( $parts as $part ) {
364
			if ( $part->getMimeType() === $type ) {
365
				break;
366
			}
367
		}
368
369
		return isset($part) ? $part : null;
370
371
	}
372
373
	public function getBody( $type = 'text/plain' )
374
	{
375
		$part = $this->getBodyPart( $type );
376
		$body = $part->getBody();
377
378
		return $body->getData();
379
	}
380
381
	/**
382
	 * Get's the gmail information from the Mail
383
	 *
384
	 * @return Mail
385
	 */
386
	public function load()
387
	{
388
		$message = $this->service->users_messages->get( 'me', $this->getId() );
389
390
		return new self( $message );
391
	}
392
393
	private function buildHeaders( $emailHeaders )
394
	{
395
		$headers = [];
396
397
		foreach ( $emailHeaders as $header ) {
398
			/** @var \Google_Service_Gmail_MessagePartHeader $header */
399
400
			$head = new \stdClass();
401
402
			$head->key = $header->getName();
403
			$head->value = $header->getValue();
404
405
			$headers[] = $head;
406
		}
407
408
		return collect( $headers );
409
410
	}
411
412
	/**
413
	 * Returns an array of emails from an string in RFC 822 format
414
	 *
415
	 * @param string $emails email list in RFC 822 format
416
	 *
417
	 * @return array
418
	 */
419
	public function formatEmailList( $emails )
420
	{
421
		$all = [];
422
		$explodedEmails = explode( ',', $emails );
423
424
		foreach ( $explodedEmails as $email ) {
425
426
			$item = [];
427
428
			preg_match( '/<(.*)>/', $email, $matches );
429
430
			$item[ 'email' ] = str_replace( ' ', '', isset( $matches[ 1 ] ) ? $matches[ 1 ] : $email );
431
432
			$name = preg_replace( '/ <(.*)>/', '', $email );
433
434
			if ( starts_with( $name, ' ' ) ) {
435
				$name = substr( $name, 1 );
436
			}
437
438
			$item[ 'name' ] = str_replace( "\"", '', $name ?: null );
439
440
			$all[] = $item;
441
442
		}
443
444
		return $all;
445
	}
446
447
	/**
448
	 * Sets the access token in case we wanna use a different token
449
	 *
450
	 * @param string $token
451
	 *
452
	 * @return Mail
453
	 */
454
	public function using( $token )
455
	{
456
		$this->setToken($token);
457
458
		return $this;
459
	}
460
461
}