master

laravel/framework

Last updated at: 29/12/2023 09:21

CommandBuilder.php

TLDR

This file contains the CommandBuilder class, which is responsible for building the command for a given event in the Laravel Console Scheduling package.

Methods

buildCommand

Builds the command for the given event. If the event should run in the background, it calls the buildBackgroundCommand method. Otherwise, it calls the buildForegroundCommand method.

buildForegroundCommand

Builds the command for running the event in the foreground. It escapes the event's output, appends it to the command, and redirects the output to the specified file. Additionally, it ensures the correct user is used to execute the command.

buildBackgroundCommand

Builds the command for running the event in the background. It escapes the event's output and determines the redirect based on whether output should be appended or overwritten. It also appends a command to mark the event as finished. The method handles specific logic for Windows operating systems and correct user execution.

ensureCorrectUser

Finalizes the event's command syntax with the correct user. If the event has a specified user and the operating system is not Windows, it adds the sudo -u command prefix with the user. Otherwise, it returns the command as is.

<?php

namespace Illuminate\Console\Scheduling;

use Illuminate\Console\Application;
use Illuminate\Support\ProcessUtils;

class CommandBuilder
{
    /**
     * Build the command for the given event.
     *
     * @param  \Illuminate\Console\Scheduling\Event  $event
     * @return string
     */
    public function buildCommand(Event $event)
    {
        if ($event->runInBackground) {
            return $this->buildBackgroundCommand($event);
        }

        return $this->buildForegroundCommand($event);
    }

    /**
     * Build the command for running the event in the foreground.
     *
     * @param  \Illuminate\Console\Scheduling\Event  $event
     * @return string
     */
    protected function buildForegroundCommand(Event $event)
    {
        $output = ProcessUtils::escapeArgument($event->output);

        return $this->ensureCorrectUser(
            $event, $event->command.($event->shouldAppendOutput ? ' >> ' : ' > ').$output.' 2>&1'
        );
    }

    /**
     * Build the command for running the event in the background.
     *
     * @param  \Illuminate\Console\Scheduling\Event  $event
     * @return string
     */
    protected function buildBackgroundCommand(Event $event)
    {
        $output = ProcessUtils::escapeArgument($event->output);

        $redirect = $event->shouldAppendOutput ? ' >> ' : ' > ';

        $finished = Application::formatCommandString('schedule:finish').' "'.$event->mutexName().'"';

        if (windows_os()) {
            return 'start /b cmd /v:on /c "('.$event->command.' & '.$finished.' ^!ERRORLEVEL^!)'.$redirect.$output.' 2>&1"';
        }

        return $this->ensureCorrectUser($event,
            '('.$event->command.$redirect.$output.' 2>&1 ; '.$finished.' "$?") > '
            .ProcessUtils::escapeArgument($event->getDefaultOutput()).' 2>&1 &'
        );
    }

    /**
     * Finalize the event's command syntax with the correct user.
     *
     * @param  \Illuminate\Console\Scheduling\Event  $event
     * @param  string  $command
     * @return string
     */
    protected function ensureCorrectUser(Event $event, $command)
    {
        return $event->user && ! windows_os() ? 'sudo -u '.$event->user.' -- sh -c \''.$command.'\'' : $command;
    }
}