Skip to content

Commit 0ebf33e

Browse files
authored
Merge pull request #39 from joelbutcher/fix-mail-facade-instance-swap
Fix the `Mail::swap()` facade override used in Laravel 10
2 parents f0ee2ac + a064e60 commit 0ebf33e

File tree

4 files changed

+156
-108
lines changed

4 files changed

+156
-108
lines changed

src/CreatesMailers.php

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
3+
namespace BeyondCode\HeloLaravel;
4+
5+
use Illuminate\Support\Arr;
6+
use Illuminate\Support\Str;
7+
8+
trait CreatesMailers
9+
{
10+
protected function createLaravel6Mailer($app)
11+
{
12+
$config = $this->getConfig();
13+
14+
// Once we have create the mailer instance, we will set a container instance
15+
// on the mailer. This allows us to resolve mailer classes via containers
16+
// for maximum testability on said classes instead of passing Closures.
17+
$mailer = new Mailer(
18+
$app['view'], $app['swift.mailer'], $app['events']
19+
);
20+
21+
if ($app->bound('queue')) {
22+
$mailer->setQueue($app['queue']);
23+
}
24+
25+
// Next we will set all of the global addresses on this mailer, which allows
26+
// for easy unification of all "from" addresses as well as easy debugging
27+
// of sent messages since they get be sent into a single email address.
28+
foreach (['from', 'reply_to', 'to'] as $type) {
29+
$this->setGlobalAddress($mailer, $config, $type);
30+
}
31+
32+
return $mailer;
33+
}
34+
35+
protected function createLaravel7Mailer($app)
36+
{
37+
$defaultDriver = $app['mail.manager']->getDefaultDriver();
38+
$config = $this->getConfig($defaultDriver);
39+
40+
// Laravel 7 no longer bindes the swift.mailer:
41+
$swiftMailer = new Swift_Mailer($app['mail.manager']->createTransport($config));
42+
43+
// Once we have create the mailer instance, we will set a container instance
44+
// on the mailer. This allows us to resolve mailer classes via containers
45+
// for maximum testability on said classes instead of passing Closures.
46+
$mailer = new Laravel7Mailer(
47+
'smtp', $app['view'], $swiftMailer, $app['events']
48+
);
49+
50+
if ($app->bound('queue')) {
51+
$mailer->setQueue($app['queue']);
52+
}
53+
54+
// Next we will set all of the global addresses on this mailer, which allows
55+
// for easy unification of all "from" addresses as well as easy debugging
56+
// of sent messages since they get be sent into a single email address.
57+
foreach (['from', 'reply_to', 'to', 'return_path'] as $type) {
58+
$this->setGlobalAddress($mailer, $config, $type);
59+
}
60+
61+
return $mailer;
62+
}
63+
64+
protected function createLaravel9Mailer($app)
65+
{
66+
$defaultDriver = $app['mail.manager']->getDefaultDriver();
67+
$config = $this->getConfig($defaultDriver);
68+
69+
// We get Symfony Transport from Laravel 9 mailer
70+
$symfonyTransport = $app['mail.manager']->getSymfonyTransport();
71+
72+
// Once we have create the mailer instance, we will set a container instance
73+
// on the mailer. This allows us to resolve mailer classes via containers
74+
// for maximum testability on said classes instead of passing Closures.
75+
$mailer = new Laravel7Mailer(
76+
'smtp', $app['view'], $symfonyTransport, $app['events']
77+
);
78+
79+
if ($app->bound('queue')) {
80+
$mailer->setQueue($app['queue']);
81+
}
82+
83+
// Next we will set all of the global addresses on this mailer, which allows
84+
// for easy unification of all "from" addresses as well as easy debugging
85+
// of sent messages since they get be sent into a single email address.
86+
foreach (['from', 'reply_to', 'to', 'return_path'] as $type) {
87+
$this->setGlobalAddress($mailer, $config, $type);
88+
}
89+
90+
return $mailer;
91+
}
92+
93+
protected function getConfig($name = 'smtp')
94+
{
95+
return $this->app['config']['mail.driver']
96+
? $this->app['config']['mail']
97+
: $this->app['config']["mail.mailers.{$name}"];
98+
}
99+
100+
/**
101+
* Set a global address on the mailer by type.
102+
*
103+
* @param \Illuminate\Mail\Mailer $mailer
104+
* @param array $config
105+
* @param string $type
106+
* @return void
107+
*/
108+
protected function setGlobalAddress($mailer, array $config, $type)
109+
{
110+
if (version_compare(app()->version(), '7.0.0', '<')) {
111+
$address = Arr::get($config, $type);
112+
} else {
113+
$address = Arr::get($config, $type, $this->app['config']['mail.'.$type]);
114+
}
115+
116+
if (is_array($address) && isset($address['address'])) {
117+
$mailer->{'always' . Str::studly($type)}($address['address'], $address['name']);
118+
}
119+
}
120+
}

src/HeloLaravelServiceProvider.php

Lines changed: 15 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
namespace BeyondCode\HeloLaravel;
44

55
use Illuminate\Contracts\Mail\Mailer as MailerContract;
6-
use Illuminate\Support\Arr;
76
use Illuminate\Support\Facades\Mail;
87
use Illuminate\Support\Facades\View;
98
use Illuminate\Support\ServiceProvider;
10-
use Illuminate\Support\Str;
119
use Swift_Mailer;
1210

1311
class HeloLaravelServiceProvider extends ServiceProvider
1412
{
13+
use CreatesMailers;
14+
1515
/**
1616
* Bootstrap the application services.
1717
*/
@@ -21,11 +21,8 @@ public function boot()
2121
return;
2222
}
2323

24-
$instance = app()->make(Mailer::class);
25-
26-
Mail::swap($instance);
2724

28-
app()->instance(MailerContract::class, $instance);
25+
$this->bootMailable();
2926

3027
if ($this->app->runningInConsole()) {
3128
View::addNamespace('helo', __DIR__ . '/../resources/views');
@@ -50,7 +47,7 @@ public function register()
5047
$this->mergeConfigFrom(__DIR__.'/../config/helo.php', 'helo');
5148

5249
$this->app->singleton(Mailer::class, function ($app) {
53-
$version = (int) Str::of($app->version())->explode('.')->first();
50+
$version = $this->version($app);
5451

5552
if ($version < 7) {
5653
return $this->createLaravel6Mailer($app);
@@ -63,114 +60,25 @@ public function register()
6360
});
6461
}
6562

66-
protected function createLaravel6Mailer($app)
63+
protected function bootMailable()
6764
{
68-
$config = $this->getConfig();
65+
if ($this->version() < 10) {
66+
$instance = app()->make(Mailer::class);
6967

70-
// Once we have create the mailer instance, we will set a container instance
71-
// on the mailer. This allows us to resolve mailer classes via containers
72-
// for maximum testability on said classes instead of passing Closures.
73-
$mailer = new Mailer(
74-
$app['view'], $app['swift.mailer'], $app['events']
75-
);
68+
Mail::swap($instance);
7669

77-
if ($app->bound('queue')) {
78-
$mailer->setQueue($app['queue']);
79-
}
80-
81-
// Next we will set all of the global addresses on this mailer, which allows
82-
// for easy unification of all "from" addresses as well as easy debugging
83-
// of sent messages since they get be sent into a single email address.
84-
foreach (['from', 'reply_to', 'to'] as $type) {
85-
$this->setGlobalAddress($mailer, $config, $type);
86-
}
87-
88-
return $mailer;
89-
}
90-
91-
protected function createLaravel7Mailer($app)
92-
{
93-
$defaultDriver = $app['mail.manager']->getDefaultDriver();
94-
$config = $this->getConfig($defaultDriver);
95-
96-
// Laravel 7 no longer bindes the swift.mailer:
97-
$swiftMailer = new Swift_Mailer($app['mail.manager']->createTransport($config));
98-
99-
// Once we have create the mailer instance, we will set a container instance
100-
// on the mailer. This allows us to resolve mailer classes via containers
101-
// for maximum testability on said classes instead of passing Closures.
102-
$mailer = new Laravel7Mailer(
103-
'smtp', $app['view'], $swiftMailer, $app['events']
104-
);
105-
106-
if ($app->bound('queue')) {
107-
$mailer->setQueue($app['queue']);
108-
}
109-
110-
// Next we will set all of the global addresses on this mailer, which allows
111-
// for easy unification of all "from" addresses as well as easy debugging
112-
// of sent messages since they get be sent into a single email address.
113-
foreach (['from', 'reply_to', 'to', 'return_path'] as $type) {
114-
$this->setGlobalAddress($mailer, $config, $type);
115-
}
116-
117-
return $mailer;
118-
}
119-
120-
protected function createLaravel9Mailer($app)
121-
{
122-
$defaultDriver = $app['mail.manager']->getDefaultDriver();
123-
$config = $this->getConfig($defaultDriver);
124-
125-
// We get Symfony Transport from Laravel 9 mailer
126-
$symfonyTransport = $app['mail.manager']->getSymfonyTransport();
127-
128-
// Once we have create the mailer instance, we will set a container instance
129-
// on the mailer. This allows us to resolve mailer classes via containers
130-
// for maximum testability on said classes instead of passing Closures.
131-
$mailer = new Laravel7Mailer(
132-
'smtp', $app['view'], $symfonyTransport, $app['events']
133-
);
134-
135-
if ($app->bound('queue')) {
136-
$mailer->setQueue($app['queue']);
137-
}
138-
139-
// Next we will set all of the global addresses on this mailer, which allows
140-
// for easy unification of all "from" addresses as well as easy debugging
141-
// of sent messages since they get be sent into a single email address.
142-
foreach (['from', 'reply_to', 'to', 'return_path'] as $type) {
143-
$this->setGlobalAddress($mailer, $config, $type);
70+
$this->app->instance(MailerContract::class, $instance);
71+
} else {
72+
Mail::swap(new MailManager($this->app));
14473
}
145-
146-
return $mailer;
147-
}
148-
149-
protected function getConfig($name = 'smtp')
150-
{
151-
return $this->app['config']['mail.driver']
152-
? $this->app['config']['mail']
153-
: $this->app['config']["mail.mailers.{$name}"];
15474
}
15575

156-
/**
157-
* Set a global address on the mailer by type.
158-
*
159-
* @param \Illuminate\Mail\Mailer $mailer
160-
* @param array $config
161-
* @param string $type
162-
* @return void
163-
*/
164-
protected function setGlobalAddress($mailer, array $config, $type)
76+
private function version($app = null): int
16577
{
166-
if (version_compare(app()->version(), '7.0.0', '<')) {
167-
$address = Arr::get($config, $type);
168-
} else {
169-
$address = Arr::get($config, $type, $this->app['config']['mail.'.$type]);
78+
if (! $app) {
79+
$app = $this->app;
17080
}
17181

172-
if (is_array($address) && isset($address['address'])) {
173-
$mailer->{'always' . Str::studly($type)}($address['address'], $address['name']);
174-
}
82+
return (int) collect(explode('.', $app->version()))->first();
17583
}
17684
}

src/MailManager.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace BeyondCode\HeloLaravel;
4+
5+
use Illuminate\Contracts\Mail\Factory as FactoryContract;
6+
use Illuminate\Mail\MailManager as LaravelMailManager;
7+
8+
class MailManager extends LaravelMailManager implements FactoryContract
9+
{
10+
use CreatesMailers;
11+
12+
public function mailer($name = null)
13+
{
14+
if (! $name) {
15+
return $this->createLaravel9Mailer($this->app);
16+
}
17+
18+
return $this->mailers[$name] = $this->get($name);
19+
}
20+
}

src/Mailer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function send($view, array $data = [], $callback = null)
2727
protected function applyDebugHeaders(Mailable $mailable)
2828
{
2929
$methodName = method_exists($mailable, 'withSymfonyMessage') ? 'withSymfonyMessage' : 'withSwiftMessage';
30-
30+
3131
$mailable->$methodName(function ($message) use ($mailable) {
3232
$viewFile = $view = $viewContent = $viewData = null;
3333

0 commit comments

Comments
 (0)