Completed
Push — master ( 2d3dcc...9dbdcf )
by Daniel
04:02
created

Replyable::__construct()   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 0
1
<?php
2
3
namespace Dacastro4\LaravelGmail\Traits;
4
5
use Dacastro4\LaravelGmail\Services\Message\Mail;
6
use Google_Service_Gmail;
7
use Google_Service_Gmail_Message;
8
use Illuminate\Support\Facades\Storage;
9
use Swift_Attachment;
10
use Swift_Message;
11
12
/**
13
 * @property Google_Service_Gmail $service
14
 */
15
trait Replyable
16
{
17
18
	private $swiftMessage;
19
20
	/**
21
	 * Gmail optional parameters
22
	 *
23
	 * @var array
24
	 */
25
	private $parameters = [];
26
27
	/**
28
	 * Text or html message to send
29
	 *
30
	 * @var string
31
	 */
32
	private $message;
33
34
	/**
35
	 * Subject of the email
36
	 *
37
	 * @var string
38
	 */
39
	private $subject;
40
41
	/**
42
	 * Sender's email
43
	 *
44
	 * @var string
45
	 */
46
	private $from;
47
48
	/**
49
	 * Sender's name
50
	 *
51
	 * @var  string
52
	 */
53
	private $nameFrom;
54
55
	/**
56
	 * Email of the recipient
57
	 *
58
	 * @var string
59
	 */
60
	private $to;
61
62
	/**
63
	 * Name of the recipient
64
	 *
65
	 * @var string
66
	 */
67
	private $nameTo;
68
69
	/**
70
	 * Single email or array of email for a carbon copy
71
	 *
72
	 * @var array|string
73
	 */
74
	private $cc;
75
76
	/**
77
	 * Name of the recipient
78
	 *
79
	 * @var string
80
	 */
81
	private $nameCc;
82
83
	/**
84
	 * Single email or array of email for a blind carbon copy
85
	 *
86
	 * @var array|string
87
	 */
88
	private $bcc;
89
90
	/**
91
	 * Name of the recipient
92
	 *
93
	 * @var string
94
	 */
95
	private $nameBcc;
96
97
	/**
98
	 * List of attachments
99
	 *
100
	 * @var array
101
	 */
102
	private $attachments = [];
103
104
	private $priority = 2;
105
106
	public function __construct()
107
	{
108
		$this->swiftMessage = new Swift_Message();
109
	}
110
111
	/**
112
	 * Receives the recipient's
113
	 * If multiple recipients will receive the message an array should be used.
114
	 * Example: array('[email protected]', '[email protected]' => 'A name')
115
	 *
116
	 * If $name is passed and the first parameter is a string, this name will be
117
	 * associated with the address.
118
	 *
119
	 * @param string|array $to
120
	 *
121
	 * @param string|null $name
122
	 *
123
	 * @return $this
124
	 */
125
	public function to( $to, $name = null )
126
	{
127
		$this->to = $to;
0 ignored issues
show
Documentation Bug introduced by
It seems like $to can also be of type array. However, the property $to is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
128
		$this->nameTo = $name;
129
130
		return $this;
131
	}
132
133
	public function from( $from, $name = null )
134
	{
135
		$this->from = $from;
136
		$this->nameTo = $name;
137
138
		return $this;
139
	}
140
141
	/**
142
	 * @param array|string $cc
143
	 *
144
	 * @param string|null $name
145
	 *
146
	 * @return $this
147
	 */
148
	public function cc( $cc, $name = null )
149
	{
150
		$this->cc = $this->emailList( $cc );
151
		$this->nameCc = $name;
152
153
		return $this;
154
	}
155
156
	/**
157
	 * @param array|string $bcc
158
	 *
159
	 * @param string|null $name
160
	 *
161
	 * @return $this
162
	 */
163
	public function bcc( $bcc, $name = null )
164
	{
165
		$this->bcc = $this->emailList( $bcc );
166
		$this->nameBcc = $name;
167
168
		return $this;
169
	}
170
171
	/**
172
	 * @param string $subject
173
	 *
174
	 * @return $this
175
	 */
176
	public function subject( $subject )
177
	{
178
		$this->subject = $subject;
179
180
		return $this;
181
	}
182
183
	/**
184
	 * @param string $message
185
	 *
186
	 * @return $this
187
	 */
188
	public function message( $message )
189
	{
190
		$this->message = $message;
191
192
		return $this;
193
	}
194
195
	/**
196
	 * Attaches new file to the email from the Storage folder
197
	 *
198
	 * @param $path
199
	 *
200
	 * @return $this
201
	 * @throws \Exception
202
	 */
203
	public function attach( $path )
204
	{
205
206
		//TODO: Solve the attach issue. Which files should I attach? UploadFile it's an option.
207
		if ( Storage::has( $path ) ) {
208
			$content = Storage::get( $path );
209
			$name = Storage::name( $path );
210
			$file[ $name ] = $content;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$file was never initialized. Although not strictly required by PHP, it is generally a good practice to add $file = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
211
		} else {
212
			throw new \Exception( 'File does not exists.' );
213
		}
214
215
		array_push( $this->attachments, $file );
216
217
		return $this;
218
	}
219
220
	/**
221
	 * The value is an integer where 1 is the highest priority and 5 is the lowest.
222
	 *
223
	 * @param int $priority
224
	 *
225
	 * @return $this
226
	 */
227
	public function priority( $priority )
228
	{
229
		$this->priority = $priority;
230
231
		return $this;
232
	}
233
234
	/**
235
	 * @param array $parameters
236
	 *
237
	 * @return $this
238
	 */
239
	public function optionalParameters( array $parameters )
240
	{
241
		$this->parameters = $parameters;
242
243
		return $this;
244
	}
245
246
	/**
247
	 * Reply to a specific email
248
	 *
249
	 * @return Mail
250
	 */
251
	public function reply()
252
	{
253
		$this->setReplyThreat();
254
		$this->setReplySubject();
255
		$body = $this->getBody();
256
		$body->setThreadId( $this->getThreatId() );
0 ignored issues
show
Bug introduced by
It seems like getThreatId() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
257
258
		return new Mail( $this->service->users_messages->send( 'me', $body, $this->parameters ) );
259
	}
260
261
	/**
262
	 * Sends a new email
263
	 *
264
	 * @return Mail
265
	 */
266
	public function send()
267
	{
268
		//TODO: How to send email
269
270
		return new Mail( $this->service->users_messages->send( 'me', $this->body, $this->parameters ) );
0 ignored issues
show
Bug introduced by
The property body does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
271
	}
272
273
	/**
274
	 * Add a header to the email
275
	 *
276
	 * @param string $header
277
	 * @param string $value
278
	 */
279
	public function setHeader( $header, $value )
280
	{
281
		$headers = $this->swiftMessage->getHeaders();
282
283
		$headers->addTextHeader( $header, $value );
284
285
	}
286
287
	/**
288
	 * @return Google_Service_Gmail_Message
289
	 */
290
	private function getBody()
291
	{
292
		$body = new Google_Service_Gmail_Message();
293
294
		$this->swiftMessage
295
			->setSubject( $this->subject )
296
			->setFrom( $this->from, $this->nameFrom )
297
			->setTo( $this->to, $this->nameTo )
298
			->setCc( $this->cc, $this->nameCc )
299
			->setBcc( $this->bcc, $this->nameBcc )
300
			->setBody( $this->message, 'text/html' )
301
			->setPriority( $this->priority );
302
303
		foreach ( $this->attachments as $file ) {
304
			$this->swiftMessage
305
				->attach( Swift_Attachment::fromPath( $file->path )->setFilename( $file->name ) );
306
		}
307
308
		$body->setRaw( $this->base64_encode( $this->swiftMessage->toString() ) );
309
310
		return $body;
311
	}
312
313
	private function base64_encode( $data )
314
	{
315
		return rtrim( strtr( base64_encode( $data ), '+/', '-_' ), '=' );
316
	}
317
318
	private function emailList( $list )
319
	{
320
		if ( is_array( $list ) ) {
321
			return implode( ', ', $list );
322
		} else {
323
			return $list;
324
		}
325
	}
326
327
	private function setReplySubject()
328
	{
329
		if ( ! $this->subject ) {
330
			$this->subject = $this->getSubject();
0 ignored issues
show
Bug introduced by
The method getSubject() does not exist on Dacastro4\LaravelGmail\Traits\Replyable. Did you maybe mean subject()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
331
		}
332
	}
333
334
	private function setReplyThreat()
335
	{
336
		$threatId = $this->getThreatId();
0 ignored issues
show
Bug introduced by
It seems like getThreatId() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
337
		if ( $threatId ) {
338
			$this->setHeader( 'In-Reply-To', $this->getHeader( 'In-Reply-To' ) );
0 ignored issues
show
Bug introduced by
It seems like getHeader() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
339
			$this->setHeader( 'References', $this->getHeader( 'References' ) );
0 ignored issues
show
Bug introduced by
It seems like getHeader() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
340
			$this->setHeader( 'Message-ID', $this->getHeader( 'Message-ID' ) );
0 ignored issues
show
Bug introduced by
It seems like getHeader() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
341
		}
342
	}
343
}