/home/bdqbpbxa/api-uniferx.goodface.com.ua/vendor/laravel/nova/src/Actions/DispatchAction.php
<?php
namespace Laravel\Nova\Actions;
use Illuminate\Bus\PendingBatch;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Queue;
use Laravel\Nova\Contracts\BatchableAction;
use Laravel\Nova\Fields\ActionFields;
use Laravel\Nova\Http\Requests\ActionRequest;
use Laravel\Nova\Nova;
class DispatchAction
{
/**
* The request instance.
*
* @var \Laravel\Nova\Http\Requests\ActionRequest
*/
protected $request;
/**
* The action instance.
*
* @var \Laravel\Nova\Actions\Action
*/
protected $action;
/**
* The fields for action instance.
*
* @var \Laravel\Nova\Fields\ActionFields
*/
protected $fields;
/**
* The pending batch instance (if the action implements BatchableAction).
*
* @var \Illuminate\Bus\PendingBatch|null
*/
protected $batchJob;
/**
* Set dispatchable callback.
*
* @var (callable(\Laravel\Nova\Actions\Response):(mixed))|null
*/
protected $dispatchableCallback;
/**
* Create a new action dispatcher instance.
*
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
* @param \Laravel\Nova\Actions\Action $action
* @param \Laravel\Nova\Fields\ActionFields $fields
* @return void
*/
public function __construct(ActionRequest $request, Action $action, ActionFields $fields)
{
$this->request = $request;
$this->action = $action;
$this->fields = $fields;
if ($action instanceof BatchableAction) {
$this->configureBatchJob($action, $fields);
}
}
/**
* Configure the batch job for the action.
*
* @param \Laravel\Nova\Actions\Action $action
* @param \Laravel\Nova\Fields\ActionFields $fields
* @return void
*/
protected function configureBatchJob(Action $action, ActionFields $fields)
{
$this->batchJob = tap(Bus::batch([]), function (PendingBatch $batch) use ($action, $fields) {
$batch->name($action->name());
if (! is_null($connection = $this->connection())) {
$batch->onConnection($connection);
}
if (! is_null($queue = $this->queue())) {
$batch->onQueue($queue);
}
$action->withBatch($fields, $batch);
});
}
/**
* Dispatch the action.
*
* @return \Laravel\Nova\Actions\Response
*
* @throws \Throwable
*/
public function dispatch()
{
if ($this->action instanceof ShouldQueue) {
return tap(new Response(), function ($response) {
with($response, $this->dispatchableCallback);
if (! is_null($this->batchJob)) {
$this->batchJob->dispatch();
}
return $response->successful();
});
}
return with(new Response(), $this->dispatchableCallback);
}
/**
* Dispatch the given action.
*
* @param string $method
* @return $this
*
* @throws \Throwable
*/
public function handleStandalone($method)
{
$this->dispatchableCallback = function (Response $response) use ($method) {
if ($this->action instanceof ShouldQueue) {
$this->addQueuedActionJob($method, collect());
return;
}
return $response->successful([
$this->dispatchSynchronouslyForCollection($method, collect()),
]);
};
return $this;
}
/**
* Dispatch the given action.
*
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
* @param string $method
* @param int $chunkCount
* @return $this
*
* @throws \Throwable
*/
public function handleRequest(ActionRequest $request, $method, $chunkCount)
{
$this->dispatchableCallback = function (Response $response) use ($request, $method, $chunkCount) {
if ($this->action instanceof ShouldQueue) {
$request->chunks($chunkCount, function ($models) use ($request, $method) {
$models = $models->filterForExecution($request);
return $this->forModels($method, $models);
});
return;
}
$wasExecuted = false;
$results = $request->chunks(
$chunkCount, function ($models) use ($request, $method, &$wasExecuted) {
$models = $models->filterForExecution($request);
if (count($models) > 0) {
$wasExecuted = true;
}
return $this->forModels($method, $models);
}
);
return $wasExecuted ? $response->successful($results) : $response->failed();
};
return $this;
}
/**
* Dispatch the given action using custom handler.
*
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
* @param \Closure(\Laravel\Nova\Http\Requests\ActionRequest, \Laravel\Nova\Actions\Response, \Laravel\Nova\Fields\ActionFields):\Laravel\Nova\Actions\Response $callback
* @return $this
*/
public function handleUsing(ActionRequest $request, $callback)
{
$this->dispatchableCallback = function (Response $response) use ($request, $callback) {
return $callback($request, $response, $this->fields);
};
return $this;
}
/**
* Dispatch the given action.
*
* @param string $method
* @param \Illuminate\Support\Collection $models
* @return mixed|void
*
* @throws \Throwable
*/
public function forModels($method, Collection $models)
{
if ($this->action->isStandalone() || $models->isEmpty()) {
return;
}
if ($this->action instanceof ShouldQueue) {
$this->addQueuedActionJob($method, $models);
return;
}
return $this->dispatchSynchronouslyForCollection($method, $models);
}
/**
* Dispatch the given action synchronously for a model collection.
*
* @param string $method
* @param \Illuminate\Support\Collection $models
* @return mixed
*
* @throws \Throwable
*/
protected function dispatchSynchronouslyForCollection($method, Collection $models)
{
return Transaction::run(function ($batchId) use ($method, $models) {
Nova::usingActionEvent(function ($actionEvent) use ($batchId, $models) {
if (! $this->action->withoutActionEvents) {
$actionEvent->createForModels(
$this->request, $this->action, $batchId, $models
);
}
});
return $this->action->withActionBatchId($batchId)->{$method}($this->fields, $models);
}, function ($batchId) {
Nova::usingActionEvent(function ($actionEvent) use ($batchId) {
if (! $this->action->withoutActionEvents) {
$actionEvent->markBatchAsFinished($batchId);
}
});
});
}
/**
* Dispatch the given action to the queue for a model collection.
*
* @param string $method
* @param \Illuminate\Support\Collection $models
* @return mixed
*
* @throws \Throwable
*/
protected function addQueuedActionJob($method, Collection $models)
{
return Transaction::run(function ($batchId) use ($method, $models) {
Nova::usingActionEvent(function ($actionEvent) use ($batchId, $models) {
if (! $this->action->withoutActionEvents) {
$actionEvent->createForModels(
$this->request, $this->action, $batchId, $models, 'waiting'
);
}
});
$job = new CallQueuedAction(
$this->action, $method, $this->request->resolveFields(), $models, $batchId
);
if ($this->action instanceof BatchableAction) {
$this->batchJob->add([$job]);
$this->batchJob->options['resourceIds'] = array_values(array_unique(array_merge(
$this->batchJob->options['resourceIds'] ?? [],
$models->map(function ($model) {
return $model->getKey();
})->all()
)));
} else {
Queue::connection($this->connection())->pushOn(
$this->queue(), $job
);
}
});
}
/**
* Extract the queue connection for the action.
*
* @return string|null
*/
protected function connection()
{
return property_exists($this->action, 'connection') ? $this->action->connection : null;
}
/**
* Extract the queue name for the action.
*
* @return string|null
*/
protected function queue()
{
return property_exists($this->action, 'queue') ? $this->action->queue : null;
}
}