diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 9bbc248..063463c 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -12,42 +12,26 @@ jobs: strategy: matrix: php: [8.1, 8.0, 7.4, 7.3, 7.2] - laravel: [8.*, 7.*, 6.*, 5.8.*, 5.7.*, 5.6.*] + laravel: [9.*, 8.*, 7.*, 6.*] os: [ubuntu-latest] include: + - laravel: 9.* + testbench: 7.* - laravel: 8.* testbench: 6.* - laravel: 7.* testbench: 5.* - laravel: 6.* testbench: 4.* - - laravel: 5.8.* - testbench: 3.8.* - - laravel: 5.7.* - testbench: 3.7.* - - laravel: 5.6.* - testbench: 3.6.* exclude: - - laravel: 8.* + - laravel: 9.* php: 7.2 - - laravel: 5.7.* - php: 7.4 - - laravel: 5.6.* + - laravel: 9.* + php: 7.3 + - laravel: 9.* php: 7.4 - - laravel: 5.5.* - php: 7.4 - - laravel: 5.8.* - php: 8.0 - - laravel: 5.7.* - php: 8.0 - - laravel: 5.6.* - php: 8.0 - - laravel: 5.6.* - php: 8.1 - - laravel: 5.7.* - php: 8.1 - - laravel: 5.8.* - php: 8.1 + - laravel: 8.* + php: 7.2 - laravel: 6.* php: 8.1 - laravel: 7.* @@ -91,4 +75,4 @@ jobs: CI_DB_DATABASE: test CI_DB_USERNAME: root CI_DB_PASSWORD: root - run: vendor/bin/phpunit \ No newline at end of file + run: vendor/bin/phpunit diff --git a/README.md b/README.md index edda785..457a323 100644 --- a/README.md +++ b/README.md @@ -19,18 +19,16 @@ We feel the package is currently feature complete, but feel free to send a pull # Requirements -This package requires Laravel 5.6 or higher. +This package requires Laravel 6.0 or higher. Please check the table below for supported Laravel and PHP versions: |Laravel Version| PHP Version | |---|---| -| 5.6 | 7.2 or 7.3 -| 5.7 | 7.2 or 7.3 -| 5.8 | 7.2 or 7.3 or 7.4 | 6.x | 7.2 or 7.3 or 7.4 or 8.0 | 7.x | 7.2 or 7.3 or 7.4 or 8.0 | 8.x | 7.3 or 7.4 or 8.0 or 8.1 +| 9.x | 8.0 or 8.1 # Installation diff --git a/composer.json b/composer.json index 7430806..583fb0d 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,6 @@ }, "require-dev": { "mockery/mockery": "^1.2", - "orchestra/testbench": "^3.5 || ^3.6 || ^3.7 || ^3.8 || ^4.0 || ^5.0", - "symfony/console": "^4.4|^5.0" + "orchestra/testbench": "^3.5 || ^3.6 || ^3.7 || ^3.8 || ^4.0 || ^5.0" } } diff --git a/src/Config.php b/src/Config.php index ab5a16d..28640c4 100644 --- a/src/Config.php +++ b/src/Config.php @@ -1,5 +1,7 @@ id; } @@ -71,7 +73,7 @@ public function getId() * * @return string|null */ - public function getLabel() + public function getLabel(): ?string { return $this->label; } @@ -79,7 +81,7 @@ public function getLabel() /** * Get the e-mail recipient. * - * @return string + * @return string|array */ public function getRecipient() { @@ -89,7 +91,7 @@ public function getRecipient() /** * Get the e-mail recipient. * - * @return string + * @return string|array */ public function getRecipientAttribute() { @@ -99,9 +101,9 @@ public function getRecipientAttribute() /** * Get the e-mail from. * - * @return string + * @return array|null */ - public function getFrom() + public function getFrom(): ?array { return $this->from; } @@ -109,9 +111,9 @@ public function getFrom() /** * Get the e-mail from. * - * @return string + * @return array|null */ - public function getFromAttribute() + public function getFromAttribute(): ?array { return $this->from; } @@ -121,7 +123,7 @@ public function getFromAttribute() * * @return string|null */ - public function getFromAddress() + public function getFromAddress(): ?string { return $this->from['address'] ?? config('mail.from.address'); } @@ -131,7 +133,7 @@ public function getFromAddress() * * @return string|null */ - public function getFromName() + public function getFromName(): ?string { return $this->from['name'] ?? config('mail.from.name'); } @@ -141,7 +143,7 @@ public function getFromName() * * @return string */ - public function getRecipientsAsString() + public function getRecipientsAsString(): string { $glue = ', '; @@ -161,7 +163,7 @@ public function getCc() /** * Get the e-mail CC addresses. * - * @return array + * @return array|string */ public function getCcAttribute() { @@ -181,7 +183,7 @@ public function getBcc() /** * Get the e-mail BCC addresses. * - * @return array + * @return array|string */ public function getBccAttribute() { @@ -193,7 +195,7 @@ public function getBccAttribute() * * @return string */ - public function getSubject() + public function getSubject(): string { return $this->subject; } @@ -203,7 +205,7 @@ public function getSubject() * * @return string */ - public function getSubjectAttribute() + public function getSubjectAttribute(): string { return $this->subject; } @@ -213,7 +215,7 @@ public function getSubjectAttribute() * * @return string */ - public function getView() + public function getView(): string { return $this->view; } @@ -221,9 +223,9 @@ public function getView() /** * Get the e-mail variables. * - * @return array + * @return array|null */ - public function getVariables() + public function getVariables(): ?array { return $this->variables; } @@ -231,9 +233,9 @@ public function getVariables() /** * Get the e-mail variables. * - * @return array + * @return array|null */ - public function getVariablesAttribute() + public function getVariablesAttribute(): ?array { return $this->variables; } @@ -243,7 +245,7 @@ public function getVariablesAttribute() * * @return string */ - public function getBody() + public function getBody(): string { return $this->body; } @@ -253,7 +255,7 @@ public function getBody() * * @return string */ - public function getBodyAttribute() + public function getBodyAttribute(): string { return $this->body; } @@ -263,7 +265,7 @@ public function getBodyAttribute() * * @return array */ - public function getAttachments() + public function getAttachments(): array { return $this->attachments; } @@ -273,7 +275,7 @@ public function getAttachments() * * @return int */ - public function getAttempts() + public function getAttempts(): int { return $this->attempts; } @@ -281,9 +283,9 @@ public function getAttempts() /** * Get the queued date. * - * @return mixed + * @return string|null */ - public function getQueuedDate() + public function getQueuedDate(): ?string { return $this->queued_at; } @@ -293,7 +295,7 @@ public function getQueuedDate() * * @return Carbon */ - public function getQueuedDateAsCarbon() + public function getQueuedDateAsCarbon(): Carbon { if ($this->queued_at instanceof Carbon) { return $this->queued_at; @@ -305,9 +307,9 @@ public function getQueuedDateAsCarbon() /** * Get the scheduled date. * - * @return mixed + * @return string|null */ - public function getScheduledDate() + public function getScheduledDate(): ?string { return $this->scheduled_at; } @@ -317,7 +319,7 @@ public function getScheduledDate() * * @return bool */ - public function hasVariables() + public function hasVariables(): bool { return ! is_null($this->variables); } @@ -327,7 +329,7 @@ public function hasVariables() * * @return Carbon */ - public function getScheduledDateAsCarbon() + public function getScheduledDateAsCarbon(): Carbon { if ($this->scheduled_at instanceof Carbon) { return $this->scheduled_at; @@ -339,9 +341,9 @@ public function getScheduledDateAsCarbon() /** * Get the send date for this e-mail. * - * @return string + * @return string|null */ - public function getSendDate() + public function getSendDate(): ?string { return $this->sent_at; } @@ -349,9 +351,9 @@ public function getSendDate() /** * Get the send error. * - * @return string + * @return string|string */ - public function getError() + public function getError(): ?string { return $this->error; } @@ -361,7 +363,7 @@ public function getError() * * @return bool */ - public function hasFrom() + public function hasFrom(): bool { return is_array($this->from) && count($this->from) > 0; } @@ -371,7 +373,7 @@ public function hasFrom() * * @return bool */ - public function hasCc() + public function hasCc(): bool { return strlen($this->getRawDatabaseValue('cc')) > 0; } @@ -381,7 +383,7 @@ public function hasCc() * * @return bool */ - public function hasBcc() + public function hasBcc(): bool { return strlen($this->getRawDatabaseValue('bcc')) > 0; } @@ -391,7 +393,7 @@ public function hasBcc() * * @return bool */ - public function isScheduled() + public function isScheduled(): bool { return ! is_null($this->getScheduledDate()); } @@ -401,7 +403,7 @@ public function isScheduled() * * @return bool */ - public function isEncrypted() + public function isEncrypted(): bool { return (bool) $this->getRawDatabaseValue('encrypted'); } @@ -411,7 +413,7 @@ public function isEncrypted() * * @return bool */ - public function isSent() + public function isSent(): bool { return ! is_null($this->sent_at); } @@ -421,7 +423,7 @@ public function isSent() * * @return bool */ - public function hasFailed() + public function hasFailed(): bool { return $this->failed == 1; } @@ -431,7 +433,7 @@ public function hasFailed() * * @return void */ - public function markAsSending() + public function markAsSending(): void { $this->update([ 'attempts' => $this->attempts + 1, @@ -444,7 +446,7 @@ public function markAsSending() * * @return void */ - public function markAsSent() + public function markAsSent(): void { $now = Carbon::now()->toDateTimeString(); @@ -462,7 +464,7 @@ public function markAsSent() * @param Exception $exception * @return void */ - public function markAsFailed(Exception $exception) + public function markAsFailed(Exception $exception): void { $this->update([ 'sending' => 0, @@ -476,9 +478,9 @@ public function markAsFailed(Exception $exception) * * @return void */ - public function send() + public function send(): void { - (new Sender)->send($this); + (new Sender())->send($this); } /** @@ -486,7 +488,7 @@ public function send() * * @return void */ - public function retry() + public function retry(): void { $retry = $this->replicate(); @@ -505,7 +507,12 @@ public function retry() $retry->save(); } - public function getRawDatabaseValue($key = null, $default = null) + /** + * @param string $key + * @param mixed $default + * @return mixed + */ + public function getRawDatabaseValue(string $key = null, $default = null) { if (method_exists($this, 'getRawOriginal')) { return $this->getRawOriginal($key, $default); diff --git a/src/EmailComposer.php b/src/EmailComposer.php index 31e3397..b358565 100644 --- a/src/EmailComposer.php +++ b/src/EmailComposer.php @@ -1,5 +1,7 @@ email; } @@ -45,9 +47,9 @@ public function getEmail() * * @param string $key * @param mixed $value - * @return static + * @return self */ - public function setData($key, $value) + public function setData(string $key, $value): self { $this->data[$key] = $value; @@ -61,7 +63,7 @@ public function setData($key, $value) * @param mixed $default * @return mixed */ - public function getData($key, $default = null) + public function getData(string $key, $default = null) { if (! is_null($default) && ! $this->hasData($key)) { return $default; @@ -76,7 +78,7 @@ public function getData($key, $default = null) * @param string $key * @return bool */ - public function hasData($key) + public function hasData(string $key): bool { return isset($this->data[$key]); } @@ -85,9 +87,9 @@ public function hasData($key) * Set the e-mail label. * * @param string $label - * @return static + * @return self */ - public function label($label) + public function label(string $label): self { return $this->setData('label', $label); } @@ -95,11 +97,11 @@ public function label($label) /** * Set the e-mail from address and aname. * - * @param array $address - * @param array $name - * @return static + * @param string|null $address + * @param string|null $name + * @return self */ - public function from($address = null, $name = null) + public function from(?string $address = null, ?string $name = null): self { return $this->setData('from', compact('address', 'name')); } @@ -108,9 +110,9 @@ public function from($address = null, $name = null) * Set the e-mail recipient(s). * * @param string|array $recipient - * @return static + * @return self */ - public function recipient($recipient) + public function recipient($recipient): self { return $this->setData('recipient', $recipient); } @@ -119,9 +121,9 @@ public function recipient($recipient) * Define the carbon-copy address(es). * * @param string|array $cc - * @return static + * @return self */ - public function cc($cc) + public function cc($cc): self { return $this->setData('cc', $cc); } @@ -130,9 +132,9 @@ public function cc($cc) * Define the blind carbon-copy address(es). * * @param string|array $bcc - * @return static + * @return self */ - public function bcc($bcc) + public function bcc($bcc): self { return $this->setData('bcc', $bcc); } @@ -141,9 +143,9 @@ public function bcc($bcc) * Set the e-mail subject. * * @param string $subject - * @return static + * @return self */ - public function subject($subject) + public function subject(string $subject): self { return $this->setData('subject', $subject); } @@ -152,9 +154,9 @@ public function subject($subject) * Set the e-mail view. * * @param string $view - * @return static + * @return self */ - public function view($view) + public function view(string $view): self { return $this->setData('view', $view); } @@ -163,9 +165,9 @@ public function view($view) * Set the e-mail variables. * * @param array $variables - * @return EmailComposer + * @return self */ - public function variables($variables) + public function variables(array $variables): self { return $this->setData('variables', $variables); } @@ -176,7 +178,7 @@ public function variables($variables) * @param mixed $scheduledAt * @return Email */ - public function schedule($scheduledAt) + public function schedule($scheduledAt): Email { return $this->later($scheduledAt); } @@ -187,7 +189,7 @@ public function schedule($scheduledAt) * @param mixed $scheduledAt * @return Email */ - public function later($scheduledAt) + public function later($scheduledAt): Email { $this->setData('scheduled_at', $scheduledAt); @@ -202,7 +204,7 @@ public function later($scheduledAt) * @param \DateTimeInterface|\DateInterval|int|null $delay * @return Email */ - public function queue($connection = null, $queue = null, $delay = null) + public function queue(?string $connection = null, ?string $queue = null, $delay = null): Email { $connection = $connection ?: config('queue.default'); $queue = $queue ?: 'default'; @@ -219,13 +221,13 @@ public function queue($connection = null, $queue = null, $delay = null) * Set the Mailable. * * @param Mailable $mailable - * @return static + * @return self */ - public function mailable(Mailable $mailable) + public function mailable(Mailable $mailable): self { $this->setData('mailable', $mailable); - (new MailableReader)->read($this); + (new MailableReader())->read($this); return $this; } @@ -235,16 +237,10 @@ public function mailable(Mailable $mailable) * * @param string $file * @param array $options - * @return static + * @return self */ - public function attach($file, $options = []) + public function attach(string $file, array $options = []): self { - $validFileName = (is_string($file) && strlen($file) > 0); - - if (! $validFileName) { - return $this; - } - $attachments = $this->hasData('attachments') ? $this->getData('attachments') : []; $attachments[] = compact('file', 'options'); @@ -258,16 +254,10 @@ public function attach($file, $options = []) * @param string $data * @param string $name * @param array $options - * @return $this + * @return self */ - public function attachData($data, $name, array $options = []) + public function attachData(string $data, string $name, array $options = []): self { - $validData = (is_string($data) && strlen($data) > 0); - - if (! $validData) { - return $this; - } - $attachments = $this->hasData('rawAttachments') ? $this->getData('rawAttachments') : []; $attachments[] = compact('data', 'name', 'options'); @@ -280,14 +270,14 @@ public function attachData($data, $name, array $options = []) * * @return Email */ - public function send() + public function send(): Email { - (new Validator)->validate($this); + (new Validator())->validate($this); - (new Preparer)->prepare($this); + (new Preparer())->prepare($this); if (Config::encryptEmails()) { - (new Encrypter)->encrypt($this); + (new Encrypter())->encrypt($this); } $this->email->save(); diff --git a/src/Encrypter.php b/src/Encrypter.php index c0438a5..b61ef21 100644 --- a/src/Encrypter.php +++ b/src/Encrypter.php @@ -1,5 +1,7 @@ setEncrypted($composer); @@ -29,7 +31,7 @@ public function encrypt(EmailComposer $composer) * * @param EmailComposer $composer */ - private function setEncrypted(EmailComposer $composer) + private function setEncrypted(EmailComposer $composer): void { $composer->getEmail()->setAttribute('encrypted', 1); } @@ -39,7 +41,7 @@ private function setEncrypted(EmailComposer $composer) * * @param EmailComposer $composer */ - private function encryptRecipients(EmailComposer $composer) + private function encryptRecipients(EmailComposer $composer): void { $email = $composer->getEmail(); @@ -55,7 +57,7 @@ private function encryptRecipients(EmailComposer $composer) * * @param EmailComposer $composer */ - private function encryptFrom(EmailComposer $composer) + private function encryptFrom(EmailComposer $composer): void { $email = $composer->getEmail(); @@ -69,7 +71,7 @@ private function encryptFrom(EmailComposer $composer) * * @param EmailComposer $composer */ - private function encryptSubject(EmailComposer $composer) + private function encryptSubject(EmailComposer $composer): void { $email = $composer->getEmail(); @@ -83,7 +85,7 @@ private function encryptSubject(EmailComposer $composer) * * @param EmailComposer $composer */ - private function encryptVariables(EmailComposer $composer) + private function encryptVariables(EmailComposer $composer): void { if (! $composer->hasData('variables')) { return; @@ -101,7 +103,7 @@ private function encryptVariables(EmailComposer $composer) * * @param EmailComposer $composer */ - private function encryptBody(EmailComposer $composer) + private function encryptBody(EmailComposer $composer): void { $email = $composer->getEmail(); diff --git a/src/HasEncryptedAttributes.php b/src/HasEncryptedAttributes.php index a73984d..bdc2ebf 100644 --- a/src/HasEncryptedAttributes.php +++ b/src/HasEncryptedAttributes.php @@ -1,5 +1,7 @@ bootConfig(); $this->bootDatabase(); @@ -56,7 +58,7 @@ private function bootDatabase(): void * * @return void */ - public function register() + public function register(): void { $this->commands([ SendEmailsCommand::class, diff --git a/src/MailableReader.php b/src/MailableReader.php index 38c4872..f926540 100644 --- a/src/MailableReader.php +++ b/src/MailableReader.php @@ -1,9 +1,10 @@ call([$composer->getData('mailable'), 'build']); @@ -38,7 +39,7 @@ public function read(EmailComposer $composer) * @param string $from * @return array */ - private function convertMailableAddresses($from) + private function convertMailableAddresses($from): array { return collect($from)->map(function ($recipient) { return $recipient['address']; @@ -50,7 +51,7 @@ private function convertMailableAddresses($from) * * @param EmailComposer $composer */ - private function readRecipient(EmailComposer $composer) + private function readRecipient(EmailComposer $composer): void { $to = $this->convertMailableAddresses( $composer->getData('mailable')->to @@ -64,7 +65,7 @@ private function readRecipient(EmailComposer $composer) * * @param EmailComposer $composer */ - private function readFrom(EmailComposer $composer) + private function readFrom(EmailComposer $composer): void { $from = reset($composer->getData('mailable')->from); @@ -83,7 +84,7 @@ private function readFrom(EmailComposer $composer) * * @param EmailComposer $composer */ - private function readCc(EmailComposer $composer) + private function readCc(EmailComposer $composer): void { $cc = $this->convertMailableAddresses( $composer->getData('mailable')->cc @@ -97,7 +98,7 @@ private function readCc(EmailComposer $composer) * * @param EmailComposer $composer */ - private function readBcc(EmailComposer $composer) + private function readBcc(EmailComposer $composer): void { $bcc = $this->convertMailableAddresses( $composer->getData('mailable')->bcc @@ -111,7 +112,7 @@ private function readBcc(EmailComposer $composer) * * @param EmailComposer $composer */ - private function readSubject(EmailComposer $composer) + private function readSubject(EmailComposer $composer): void { $composer->subject($composer->getData('mailable')->subject); } @@ -122,7 +123,7 @@ private function readSubject(EmailComposer $composer) * @param EmailComposer $composer * @throws Exception */ - private function readBody(EmailComposer $composer) + private function readBody(EmailComposer $composer): void { if (app()->version() < '5.5') { throw new Exception('Mailables cannot be read by Laravel 5.4 and below. Sorry.'); @@ -140,7 +141,7 @@ private function readBody(EmailComposer $composer) * * @param EmailComposer $composer */ - private function readAttachments(EmailComposer $composer) + private function readAttachments(EmailComposer $composer): void { $mailable = $composer->getData('mailable'); diff --git a/src/MessageSent.php b/src/MessageSent.php new file mode 100644 index 0000000..3ca6e6e --- /dev/null +++ b/src/MessageSent.php @@ -0,0 +1,18 @@ +message = $message; + } +} diff --git a/src/Preparer.php b/src/Preparer.php index 60b5fec..831e0c0 100644 --- a/src/Preparer.php +++ b/src/Preparer.php @@ -1,5 +1,7 @@ prepareLabel($composer); @@ -45,7 +47,7 @@ public function prepare(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareLabel(EmailComposer $composer) + private function prepareLabel(EmailComposer $composer): void { if (! $composer->hasData('label')) { return; @@ -61,7 +63,7 @@ private function prepareLabel(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareRecipient(EmailComposer $composer) + private function prepareRecipient(EmailComposer $composer): void { if (Config::testing()) { $composer->recipient(Config::testEmailAddress()); @@ -77,7 +79,7 @@ private function prepareRecipient(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareFrom(EmailComposer $composer) + private function prepareFrom(EmailComposer $composer): void { $composer->getEmail()->fill([ 'from' => json_encode($composer->getData('from', '')), @@ -89,7 +91,7 @@ private function prepareFrom(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareCc(EmailComposer $composer) + private function prepareCc(EmailComposer $composer): void { if (Config::testing()) { $composer->setData('cc', []); @@ -105,7 +107,7 @@ private function prepareCc(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareBcc(EmailComposer $composer) + private function prepareBcc(EmailComposer $composer): void { if (Config::testing()) { $composer->setData('bcc', []); @@ -121,7 +123,7 @@ private function prepareBcc(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareSubject(EmailComposer $composer) + private function prepareSubject(EmailComposer $composer): void { $composer->getEmail()->fill([ 'subject' => $composer->getData('subject'), @@ -133,7 +135,7 @@ private function prepareSubject(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareView(EmailComposer $composer) + private function prepareView(EmailComposer $composer): void { $composer->getEmail()->fill([ 'view' => $composer->getData('view'), @@ -145,7 +147,7 @@ private function prepareView(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareVariables(EmailComposer $composer) + private function prepareVariables(EmailComposer $composer): void { if (! $composer->hasData('variables')) { return; @@ -161,7 +163,7 @@ private function prepareVariables(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareBody(EmailComposer $composer) + private function prepareBody(EmailComposer $composer): void { // If the body was predefined (by for example a mailable), use that. if ($composer->hasData('body')) { @@ -181,7 +183,7 @@ private function prepareBody(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareAttachments(EmailComposer $composer) + private function prepareAttachments(EmailComposer $composer): void { $attachments = []; @@ -209,7 +211,7 @@ private function prepareAttachments(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareScheduled(EmailComposer $composer) + private function prepareScheduled(EmailComposer $composer): void { if (! $composer->hasData('scheduled_at')) { return; @@ -231,7 +233,7 @@ private function prepareScheduled(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareImmediately(EmailComposer $composer) + private function prepareImmediately(EmailComposer $composer): void { if (Config::sendImmediately()) { $composer->getEmail()->fill(['sending' => 1]); @@ -243,7 +245,7 @@ private function prepareImmediately(EmailComposer $composer) * * @param EmailComposer $composer */ - private function prepareQueued(EmailComposer $composer) + private function prepareQueued(EmailComposer $composer): void { if ($composer->getData('queued', false) === true) { $composer->getEmail()->fill([ diff --git a/src/SendEmailJob.php b/src/SendEmailJob.php index 4ca3070..a7ba528 100644 --- a/src/SendEmailJob.php +++ b/src/SendEmailJob.php @@ -1,5 +1,6 @@ email = $email; } - public function handle() + public function handle(): void { (new Sender())->send($this->email); } diff --git a/src/SendEmailsCommand.php b/src/SendEmailsCommand.php index d1bca2d..039ca37 100644 --- a/src/SendEmailsCommand.php +++ b/src/SendEmailsCommand.php @@ -1,5 +1,7 @@ store->getQueue(); @@ -73,23 +75,13 @@ public function handle() $this->result($emails); } - /** - * Execute the console command (backwards compatibility for Laravel 5.4 and below). - * - * @return void - */ - public function fire() - { - $this->handle(); - } - /** * Output a table with the cronjob result. * * @param Collection $emails * @return void */ - protected function result($emails) + protected function result(Collection $emails): void { $headers = ['ID', 'Recipient', 'Subject', 'Status']; diff --git a/src/Sender.php b/src/Sender.php index 567819f..2a9bf63 100644 --- a/src/Sender.php +++ b/src/Sender.php @@ -1,5 +1,7 @@ isSent()) { return; @@ -20,10 +22,16 @@ public function send(Email $email) $email->markAsSending(); - Mail::send([], [], function (Message $message) use ($email) { + $sentMessage = Mail::send([], [], function (Message $message) use ($email) { $this->buildMessage($message, $email); }); + // This is used so we can assert things on the sent message in Laravel 9+ since we cannot use + // the Swift Mailer plugin anymore. So this is purely used for in the PHPUnit tests. + if (version_compare(app()->version(), '9.0.0', '>=') && !is_null($sentMessage)) { + event(new MessageSent($sentMessage)); + } + $email->markAsSent(); } @@ -33,21 +41,28 @@ public function send(Email $email) * @param Message $message * @param Email $email */ - private function buildMessage(Message $message, Email $email) + private function buildMessage(Message $message, Email $email): void { $message->to($email->getRecipient()) ->cc($email->hasCc() ? $email->getCc() : []) ->bcc($email->hasBcc() ? $email->getBcc() : []) ->subject($email->getSubject()) - ->from($email->getFromAddress(), $email->getFromName()) - ->setBody($email->getBody(), 'text/html'); + ->from($email->getFromAddress(), $email->getFromName()); + + if (version_compare(app()->version(), '9.0.0', '>=')) { + // Symfony Mailer + $message->html($email->getBody()); + } else { + // SwiftMail + $message->setBody($email->getBody(), 'text/html'); + } $attachmentMap = [ 'attachment' => 'attach', 'rawAttachment' => 'attachData', ]; - foreach ((array) $email->getAttachments() as $attachment) { + foreach ($email->getAttachments() as $attachment) { call_user_func_array([$message, $attachmentMap[$attachment['type']]], $attachment['attachment']); } } diff --git a/src/SentMessage.php b/src/SentMessage.php new file mode 100644 index 0000000..98c6156 --- /dev/null +++ b/src/SentMessage.php @@ -0,0 +1,72 @@ +getFrom() as $address) { + $sentMessage->from[$address->getAddress()] = $address->getName(); + } + + foreach ($email->getTo() as $address) { + $sentMessage->to[$address->getAddress()] = $address->getName(); + } + + foreach ($email->getCc() as $address) { + $sentMessage->cc[$address->getAddress()] = $address->getName(); + } + + foreach ($email->getBcc() as $address) { + $sentMessage->bcc[$address->getAddress()] = $address->getName(); + } + + $sentMessage->subject = $email->getSubject(); + $sentMessage->body = $email->getHtmlBody(); + $sentMessage->attachments = array_map(function (DataPart $dataPart) { + return [ + 'body' => $dataPart->getBody(), + 'disposition' => $dataPart->asDebugString(), + ]; + }, $email->getAttachments()); + + return $sentMessage; + } + + public static function createFromSwiftMailer(\Swift_Mime_SimpleMessage $message): SentMessage + { + $sentMessage = new self(); + + $sentMessage->from = $message->getFrom(); + $sentMessage->to = $message->getTo(); + $sentMessage->cc = $message->getCc(); + $sentMessage->bcc = $message->getBcc(); + $sentMessage->subject = $message->getSubject(); + $sentMessage->body = $message->getBody(); + $sentMessage->attachments = array_map(function(Swift_Mime_SimpleMimeEntity $entity) { + return [ + 'body' => $entity->getBody(), + 'disposition' => $entity->getContentType() . ' ' . $entity->getHeaders()->get('content-disposition'), + ]; + }, $message->getChildren()); + + return $sentMessage; + } +} diff --git a/src/Store.php b/src/Store.php index a6b3eb2..3a9f4f2 100644 --- a/src/Store.php +++ b/src/Store.php @@ -1,5 +1,7 @@ whereNull('deleted_at') diff --git a/src/Validator.php b/src/Validator.php index 0dfc946..038c484 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -1,5 +1,7 @@ validateLabel($composer); @@ -46,7 +48,7 @@ public function validate(EmailComposer $composer) * @param EmailComposer $composer * @throws InvalidArgumentException */ - private function validateLabel(EmailComposer $composer) + private function validateLabel(EmailComposer $composer): void { if ($composer->hasData('label') && strlen($composer->getData('label')) > 255) { throw new InvalidArgumentException('The given label [' . $composer->getData('label') . '] is too large for database storage'); @@ -59,7 +61,7 @@ private function validateLabel(EmailComposer $composer) * @param EmailComposer $composer * @throws InvalidArgumentException */ - private function validateRecipient(EmailComposer $composer) + private function validateRecipient(EmailComposer $composer): void { if (! $composer->hasData('recipient')) { throw new InvalidArgumentException('No recipient specified'); @@ -84,7 +86,7 @@ private function validateRecipient(EmailComposer $composer) * @param EmailComposer $composer * @throws InvalidArgumentException */ - private function validateCc(EmailComposer $composer) + private function validateCc(EmailComposer $composer): void { if (! $composer->hasData('cc')) { return; @@ -103,7 +105,7 @@ private function validateCc(EmailComposer $composer) * @param EmailComposer $composer * @throws InvalidArgumentException */ - private function validateBcc(EmailComposer $composer) + private function validateBcc(EmailComposer $composer): void { if (! $composer->hasData('bcc')) { return; @@ -122,7 +124,7 @@ private function validateBcc(EmailComposer $composer) * @param EmailComposer $composer * @throws InvalidArgumentException */ - private function validateSubject(EmailComposer $composer) + private function validateSubject(EmailComposer $composer): void { if (! $composer->hasData('subject')) { throw new InvalidArgumentException('No subject specified'); @@ -135,7 +137,7 @@ private function validateSubject(EmailComposer $composer) * @param EmailComposer $composer * @throws InvalidARgumentException */ - private function validateView(EmailComposer $composer) + private function validateView(EmailComposer $composer): void { if ($composer->hasData('mailable')) { return; @@ -158,7 +160,7 @@ private function validateView(EmailComposer $composer) * @param EmailComposer $composer * @throws InvalidArgumentException */ - private function validateVariables(EmailComposer $composer) + private function validateVariables(EmailComposer $composer): void { if ($composer->hasData('variables') && ! is_array($composer->getData('variables'))) { throw new InvalidArgumentException('Variables must be an array'); @@ -171,7 +173,7 @@ private function validateVariables(EmailComposer $composer) * @param EmailComposer $composer * @throws InvalidArgumentException */ - private function validateScheduled(EmailComposer $composer) + private function validateScheduled(EmailComposer $composer): void { if (! $composer->hasData('scheduled_at')) { return; diff --git a/tests/SendEmailsCommandTest.php b/tests/SendEmailsCommandTest.php index 5aacca4..ccd38d7 100644 --- a/tests/SendEmailsCommandTest.php +++ b/tests/SendEmailsCommandTest.php @@ -68,7 +68,7 @@ public function if_an_email_fails_to_be_sent_it_should_be_logged_in_the_database $this->artisan('email:send'); $this->assertTrue($email->fresh()->hasFailed()); - $this->assertStringContains('Swift_RfcComplianceException', $email->fresh()->getError()); + $this->assertStringContainsString('RfcComplianceException', $email->fresh()->getError()); } /** @test */ diff --git a/tests/SenderTest.php b/tests/SenderTest.php index 9cc2bfd..686bd50 100644 --- a/tests/SenderTest.php +++ b/tests/SenderTest.php @@ -2,6 +2,9 @@ namespace Tests; +use Illuminate\Support\Facades\Event; +use Stackkit\LaravelDatabaseEmails\MessageSent; +use Stackkit\LaravelDatabaseEmails\SentMessage; use Swift_Events_SendEvent; use Illuminate\Support\Facades\Mail; use Stackkit\LaravelDatabaseEmails\Email; @@ -15,7 +18,15 @@ public function setUp(): void { parent::setUp(); - Mail::getSwiftMailer()->registerPlugin(new TestingMailEventListener($this)); + if (version_compare(app()->version(), '9.0.0', '>=')) { + Event::listen(MessageSent::class, function (MessageSent $event) { + $this->sent[] = SentMessage::createFromSymfonyMailer( + $event->message->getSymfonySentMessage()->getOriginalMessage() + ); + }); + } else { + Mail::getSwiftMailer()->registerPlugin(new TestingMailEventListener($this)); + } } /** @test */ @@ -38,7 +49,7 @@ public function the_email_has_a_correct_from_email_and_from_name() $this->artisan('email:send'); - $from = reset($this->sent)->getMessage()->getFrom(); + $from = reset($this->sent)->from; $this->assertEquals('testfromaddress@gmail.com', key($from)); $this->assertEquals('From CI test', $from[key($from)]); @@ -48,7 +59,7 @@ public function the_email_has_a_correct_from_email_and_from_name() $this->composeEmail()->from('marick@dolphiq.nl', 'Marick')->send(); $this->artisan('email:send'); - $from = reset($this->sent)->getMessage()->getFrom(); + $from = reset($this->sent)->from; $this->assertEquals('marick@dolphiq.nl', key($from)); $this->assertEquals('Marick', $from[key($from)]); @@ -56,7 +67,7 @@ public function the_email_has_a_correct_from_email_and_from_name() $this->sent = []; $this->composeEmail()->from('marick@dolphiq.nl')->send(); $this->artisan('email:send'); - $from = reset($this->sent)->getMessage()->getFrom(); + $from = reset($this->sent)->from; $this->assertEquals('marick@dolphiq.nl', key($from)); $this->assertEquals(config('mail.from.name'), $from[key($from)]); @@ -64,7 +75,7 @@ public function the_email_has_a_correct_from_email_and_from_name() $this->sent = []; $this->composeEmail()->from(null, 'Marick')->send(); $this->artisan('email:send'); - $from = reset($this->sent)->getMessage()->getFrom(); + $from = reset($this->sent)->from; $this->assertEquals(config('mail.from.address'), key($from)); $this->assertEquals('Marick', $from[key($from)]); } @@ -74,14 +85,14 @@ public function it_sends_emails_to_the_correct_recipients() { $this->sendEmail(['recipient' => 'john@doe.com']); $this->artisan('email:send'); - $to = reset($this->sent)->getMessage()->getTo(); + $to = reset($this->sent)->to; $this->assertCount(1, $to); $this->assertArrayHasKey('john@doe.com', $to); $this->sent = []; $this->sendEmail(['recipient' => ['john@doe.com', 'john+2@doe.com']]); $this->artisan('email:send'); - $to = reset($this->sent)->getMessage()->getTo(); + $to = reset($this->sent)->to; $this->assertCount(2, $to); $this->assertArrayHasKey('john@doe.com', $to); $this->assertArrayHasKey('john+2@doe.com', $to); @@ -92,14 +103,14 @@ public function it_adds_the_cc_addresses() { $this->sendEmail(['cc' => 'cc@test.com']); $this->artisan('email:send'); - $cc = reset($this->sent)->getMessage()->getCc(); + $cc = reset($this->sent)->cc; $this->assertCount(1, $cc); $this->assertArrayHasKey('cc@test.com', $cc); $this->sent = []; $this->sendEmail(['cc' => ['cc@test.com', 'cc+2@test.com']]); $this->artisan('email:send'); - $cc = reset($this->sent)->getMessage()->getCc(); + $cc = reset($this->sent)->cc; $this->assertCount(2, $cc); $this->assertArrayHasKey('cc@test.com', $cc); $this->assertArrayHasKey('cc+2@test.com', $cc); @@ -110,14 +121,14 @@ public function it_adds_the_bcc_addresses() { $this->sendEmail(['bcc' => 'bcc@test.com']); $this->artisan('email:send'); - $bcc = reset($this->sent)->getMessage()->getBcc(); + $bcc = reset($this->sent)->bcc; $this->assertCount(1, $bcc); $this->assertArrayHasKey('bcc@test.com', $bcc); $this->sent = []; $this->sendEmail(['bcc' => ['bcc@test.com', 'bcc+2@test.com']]); $this->artisan('email:send'); - $bcc = reset($this->sent)->getMessage()->getBcc(); + $bcc = reset($this->sent)->bcc; $this->assertCount(2, $bcc); $this->assertArrayHasKey('bcc@test.com', $bcc); $this->assertArrayHasKey('bcc+2@test.com', $bcc); @@ -130,7 +141,7 @@ public function the_email_has_the_correct_subject() $this->artisan('email:send'); - $subject = reset($this->sent)->getMessage()->getSubject(); + $subject = reset($this->sent)->subject; $this->assertEquals('Hello World', $subject); } @@ -140,13 +151,13 @@ public function the_email_has_the_correct_body() { $this->sendEmail(['variables' => ['name' => 'John Doe']]); $this->artisan('email:send'); - $body = reset($this->sent)->getMessage()->getBody(); - $this->assertEquals(view('tests::dummy', ['name' => 'John Doe']), $body); + $body = reset($this->sent)->body; + $this->assertEquals((string) view('tests::dummy', ['name' => 'John Doe']), $body); $this->sent = []; $this->sendEmail(['variables' => []]); $this->artisan('email:send'); - $body = reset($this->sent)->getMessage()->getBody(); + $body = reset($this->sent)->body; $this->assertEquals(view('tests::dummy'), $body); } @@ -158,34 +169,9 @@ public function attachments_are_added_to_the_email() ->send(); $this->artisan('email:send'); - $attachments = reset($this->sent)->getMessage()->getChildren(); - $attachment = reset($attachments); + $attachments = reset($this->sent)->attachments; $this->assertCount(1, $attachments); - $this->assertEquals('attachment; filename=pdf-sample.pdf', $attachment->getHeaders()->get('content-disposition')->getFieldBody()); - $this->assertEquals('application/pdf', $attachment->getContentType()); - } - - /** @test */ - public function attachments_are_not_added_if_the_data_is_not_valid() - { - $this->sent = []; - $this->composeEmail()->attach(null)->send(); - $this->artisan('email:send'); - $attachments = reset($this->sent)->getMessage()->getChildren(); - $this->assertCount(0, $attachments); - - $this->sent = []; - $this->composeEmail()->attach(false)->send(); - $this->artisan('email:send'); - $attachments = reset($this->sent)->getMessage()->getChildren(); - $this->assertCount(0, $attachments); - - $this->sent = []; - $this->composeEmail()->attach('')->send(); - $this->artisan('email:send'); - $attachments = reset($this->sent)->getMessage()->getChildren(); - $this->assertCount(0, $attachments); } /** @test */ @@ -200,13 +186,13 @@ public function raw_attachments_are_added_to_the_email() ->send(); $this->artisan('email:send'); - $attachments = reset($this->sent)->getMessage()->getChildren(); + $attachments = reset($this->sent)->attachments; $attachment = reset($attachments); $this->assertCount(1, $attachments); - $this->assertEquals('attachment; filename=hello-ci.pdf', $attachment->getHeaders()->get('content-disposition')->getFieldBody()); - $this->assertEquals('application/pdf', $attachment->getContentType()); - $this->assertTrue(md5($attachment->getBody()) == md5($rawData)); + $this->assertStringContainsString('hello-ci.pdf', $attachment['disposition']); + $this->assertStringContainsString('application/pdf', $attachment['disposition']); + $this->assertTrue(md5($attachment['body']) == md5($rawData)); } /** @test */ @@ -239,26 +225,4 @@ public function emails_can_be_sent_immediately() $this->artisan('email:send'); $this->assertCount(1, $this->sent); } - - /** @test */ - public function raw_attachments_are_not_added_if_the_data_is_not_valid() - { - $this->sent = []; - $this->composeEmail()->attachData(null, 'test.png')->send(); - $this->artisan('email:send'); - $attachments = reset($this->sent)->getMessage()->getChildren(); - $this->assertCount(0, $attachments); - - $this->sent = []; - $this->composeEmail()->attachData(false, 'test.png')->send(); - $this->artisan('email:send'); - $attachments = reset($this->sent)->getMessage()->getChildren(); - $this->assertCount(0, $attachments); - - $this->sent = []; - $this->composeEmail()->attachData('', 'test.png')->send(); - $this->artisan('email:send'); - $attachments = reset($this->sent)->getMessage()->getChildren(); - $this->assertCount(0, $attachments); - } } diff --git a/tests/TestCase.php b/tests/TestCase.php index a2ddf40..6223864 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,7 +2,6 @@ namespace Tests; -use Eloquent; use Stackkit\LaravelDatabaseEmails\Email; class TestCase extends \Orchestra\Testbench\TestCase @@ -32,26 +31,6 @@ function () { Email::truncate(); } - /** - * Get a database connection instance. - * - * @return \Illuminate\Database\Connection - */ - protected function connection() - { - return Eloquent::getConnectionResolver()->connection(); - } - - /** - * Get a schema builder instance. - * - * @return \Illuminate\Database\Schema\Builder - */ - protected function schema() - { - return $this->connection()->getSchemaBuilder(); - } - /** * Get package providers. At a minimum this is the package being tested, but also * would include packages upon which our package depends, e.g. Cartalyst/Sentry @@ -137,13 +116,4 @@ public function queueEmail($connection = null, $queue = null, $delay = null, $ov { return $this->createEmail($overwrite)->queue($connection, $queue, $delay); } - - public function assertStringContains($needle, $haystack) - { - if (method_exists($this, 'assertStringContainsString')) { - $this->assertStringContainsString($needle, $haystack); - } else { - $this->assertContains($needle, $haystack); - } - } } diff --git a/tests/TestingMailEventListener.php b/tests/TestingMailEventListener.php index b143350..4fa32f1 100644 --- a/tests/TestingMailEventListener.php +++ b/tests/TestingMailEventListener.php @@ -2,6 +2,7 @@ namespace Tests; +use Stackkit\LaravelDatabaseEmails\SentMessage; use Swift_Events_EventListener; class TestingMailEventListener implements Swift_Events_EventListener @@ -14,8 +15,8 @@ public function __construct(TestCase $test) $this->test = $test; } - public function beforeSendPerformed($event) + public function beforeSendPerformed(\Swift_Events_Event $event) { - $this->test->sent[] = $event; + $this->test->sent[] = SentMessage::createFromSwiftMailer($event->getMessage()); } } diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index 0646c70..20f86a0 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -139,7 +139,7 @@ public function variables_must_be_defined_as_an_array() try { $email->variables($type)->send(); $this->fail('Expected exception to be thrown'); - } catch (InvalidArgumentException $e) { + } catch (\TypeError $e) { $this->assertEquals($e->getCode(), 0); } }