Skip to content

Commit 2acb803

Browse files
committed
Merge branch '10.x'
2 parents c948905 + 6f06ad4 commit 2acb803

22 files changed

+528
-36
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Illuminate\Contracts\Events;
4+
5+
interface ShouldDispatchAfterCommit
6+
{
7+
//
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Illuminate\Contracts\Events;
4+
5+
interface ShouldHandleEventsAfterCommit
6+
{
7+
//
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Illuminate\Contracts\Queue;
4+
5+
interface ShouldQueueAfterCommit extends ShouldQueue
6+
{
7+
//
8+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Illuminate\Database\Eloquent;
4+
5+
trait BroadcastsEventsAfterCommit
6+
{
7+
use BroadcastsEvents;
8+
9+
/**
10+
* Determine if the model event broadcast queued job should be dispatched after all transactions are committed.
11+
*
12+
* @return bool
13+
*/
14+
public function broadcastAfterCommit()
15+
{
16+
return true;
17+
}
18+
}

src/Illuminate/Database/Eloquent/Builder.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,29 +97,29 @@ class Builder implements BuilderContract
9797
'avg',
9898
'count',
9999
'dd',
100-
'ddRawSql',
101-
'doesntExist',
102-
'doesntExistOr',
100+
'ddrawsql',
101+
'doesntexist',
102+
'doesntexistor',
103103
'dump',
104-
'dumpRawSql',
104+
'dumprawsql',
105105
'exists',
106-
'existsOr',
106+
'existsor',
107107
'explain',
108-
'getBindings',
109-
'getConnection',
110-
'getGrammar',
108+
'getbindings',
109+
'getconnection',
110+
'getgrammar',
111111
'implode',
112112
'insert',
113-
'insertGetId',
114-
'insertOrIgnore',
115-
'insertUsing',
113+
'insertgetid',
114+
'insertorignore',
115+
'insertusing',
116116
'max',
117117
'min',
118118
'raw',
119-
'rawValue',
119+
'rawvalue',
120120
'sum',
121-
'toSql',
122-
'toRawSql',
121+
'tosql',
122+
'torawsql',
123123
];
124124

125125
/**
@@ -1964,7 +1964,7 @@ public function __call($method, $parameters)
19641964
return $this->callNamedScope($method, $parameters);
19651965
}
19661966

1967-
if (in_array($method, $this->passthru)) {
1967+
if (in_array(strtolower($method), $this->passthru)) {
19681968
return $this->toBase()->{$method}(...$parameters);
19691969
}
19701970

src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ public function withAggregate($relations, $column, $function = null)
686686
* Get the relation hashed column name for the given column and relation.
687687
*
688688
* @param string $column
689-
* @param \Illuminate\Database\Eloquent\Relations\Relationship $relation
689+
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
690690
* @return string
691691
*/
692692
protected function getRelationHashedColumn($column, $relation)

src/Illuminate/Events/Dispatcher.php

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
1010
use Illuminate\Contracts\Container\Container as ContainerContract;
1111
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
12+
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
13+
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
1214
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
1315
use Illuminate\Contracts\Queue\ShouldQueue;
16+
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
1417
use Illuminate\Support\Arr;
1518
use Illuminate\Support\Str;
1619
use Illuminate\Support\Traits\Macroable;
@@ -56,6 +59,13 @@ class Dispatcher implements DispatcherContract
5659
*/
5760
protected $queueResolver;
5861

62+
/**
63+
* The database transaction manager resolver instance.
64+
*
65+
* @var callable
66+
*/
67+
protected $transactionManagerResolver;
68+
5969
/**
6070
* Create a new event dispatcher instance.
6171
*
@@ -235,10 +245,37 @@ public function dispatch($event, $payload = [], $halt = false)
235245
// When the given "event" is actually an object we will assume it is an event
236246
// object and use the class as the event name and this event itself as the
237247
// payload to the handler, which makes object based events quite simple.
238-
[$event, $payload] = $this->parseEventAndPayload(
239-
$event, $payload
240-
);
248+
[$isEventObject, $event, $payload] = [
249+
is_object($event),
250+
...$this->parseEventAndPayload($event, $payload),
251+
];
252+
253+
// If the event is not intended to be dispatched unless the current database
254+
// transaction is successful, we'll register a callback which will handle
255+
// dispatching this event on the next successful DB transaction commit.
256+
if ($isEventObject &&
257+
$payload[0] instanceof ShouldDispatchAfterCommit &&
258+
! is_null($transactions = $this->resolveTransactionManager())) {
259+
$transactions->addCallback(
260+
fn () => $this->invokeListeners($event, $payload, $halt)
261+
);
241262

263+
return null;
264+
}
265+
266+
return $this->invokeListeners($event, $payload, $halt);
267+
}
268+
269+
/**
270+
* Broadcast an event and call its listeners.
271+
*
272+
* @param string|object $event
273+
* @param mixed $payload
274+
* @param bool $halt
275+
* @return array|null
276+
*/
277+
protected function invokeListeners($event, $payload, $halt = false)
278+
{
242279
if ($this->shouldBroadcast($payload)) {
243280
$this->broadcastEvent($payload[0]);
244281
}
@@ -525,7 +562,9 @@ protected function createQueuedHandlerCallable($class, $method)
525562
*/
526563
protected function handlerShouldBeDispatchedAfterDatabaseTransactions($listener)
527564
{
528-
return ($listener->afterCommit ?? null) && $this->container->bound('db.transactions');
565+
return (($listener->afterCommit ?? null) ||
566+
$listener instanceof ShouldHandleEventsAfterCommit) &&
567+
$this->resolveTransactionManager();
529568
}
530569

531570
/**
@@ -540,7 +579,7 @@ protected function createCallbackForListenerRunningAfterCommits($listener, $meth
540579
return function () use ($method, $listener) {
541580
$payload = func_get_args();
542581

543-
$this->container->make('db.transactions')->addCallback(
582+
$this->resolveTransactionManager()->addCallback(
544583
function () use ($listener, $method, $payload) {
545584
$listener->$method(...$payload);
546585
}
@@ -624,7 +663,12 @@ protected function propagateListenerOptions($listener, $job)
624663
return tap($job, function ($job) use ($listener) {
625664
$data = array_values($job->data);
626665

627-
$job->afterCommit = property_exists($listener, 'afterCommit') ? $listener->afterCommit : null;
666+
if ($listener instanceof ShouldQueueAfterCommit) {
667+
$job->afterCommit = true;
668+
} else {
669+
$job->afterCommit = property_exists($listener, 'afterCommit') ? $listener->afterCommit : null;
670+
}
671+
628672
$job->backoff = method_exists($listener, 'backoff') ? $listener->backoff(...$data) : ($listener->backoff ?? null);
629673
$job->maxExceptions = $listener->maxExceptions ?? null;
630674
$job->retryUntil = method_exists($listener, 'retryUntil') ? $listener->retryUntil(...$data) : null;
@@ -697,6 +741,29 @@ public function setQueueResolver(callable $resolver)
697741
return $this;
698742
}
699743

744+
/**
745+
* Get the database transaction manager implementation from the resolver.
746+
*
747+
* @return \Illuminate\Database\DatabaseTransactionsManager|null
748+
*/
749+
protected function resolveTransactionManager()
750+
{
751+
return call_user_func($this->transactionManagerResolver);
752+
}
753+
754+
/**
755+
* Set the database transaction manager resolver implementation.
756+
*
757+
* @param callable $resolver
758+
* @return $this
759+
*/
760+
public function setTransactionManagerResolver(callable $resolver)
761+
{
762+
$this->transactionManagerResolver = $resolver;
763+
764+
return $this;
765+
}
766+
700767
/**
701768
* Gets the raw, unprepared listeners.
702769
*

src/Illuminate/Events/EventServiceProvider.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ public function register()
1717
$this->app->singleton('events', function ($app) {
1818
return (new Dispatcher($app))->setQueueResolver(function () use ($app) {
1919
return $app->make(QueueFactoryContract::class);
20+
})->setTransactionManagerResolver(function () use ($app) {
21+
return $app->bound('db.transactions')
22+
? $app->make('db.transactions')
23+
: null;
2024
});
2125
});
2226
}

src/Illuminate/Http/Client/Response.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,8 @@ public function throwIfStatus($statusCode)
339339
*/
340340
public function throwUnlessStatus($statusCode)
341341
{
342-
if (is_callable($statusCode) &&
343-
! $statusCode($this->status(), $this)) {
344-
return $this->throw();
342+
if (is_callable($statusCode)) {
343+
return $statusCode($this->status(), $this) ? $this : $this->throw();
345344
}
346345

347346
return $this->status() === $statusCode ? $this : $this->throw();

src/Illuminate/Mail/SendQueuedMailable.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Contracts\Mail\Factory as MailFactory;
77
use Illuminate\Contracts\Mail\Mailable as MailableContract;
88
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
9+
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
910
use Illuminate\Queue\InteractsWithQueue;
1011

1112
class SendQueuedMailable
@@ -57,7 +58,12 @@ public function __construct(MailableContract $mailable)
5758
{
5859
$this->mailable = $mailable;
5960

60-
$this->afterCommit = property_exists($mailable, 'afterCommit') ? $mailable->afterCommit : null;
61+
if ($mailable instanceof ShouldQueueAfterCommit) {
62+
$this->afterCommit = true;
63+
} else {
64+
$this->afterCommit = property_exists($mailable, 'afterCommit') ? $mailable->afterCommit : null;
65+
}
66+
6167
$this->connection = property_exists($mailable, 'connection') ? $mailable->connection : null;
6268
$this->maxExceptions = property_exists($mailable, 'maxExceptions') ? $mailable->maxExceptions : null;
6369
$this->queue = property_exists($mailable, 'queue') ? $mailable->queue : null;

0 commit comments

Comments
 (0)