Parser.php 0000666 00000011457 13531431770 0006531 0 ustar 00 artisan = $artisan;
}
}
Events/CommandStarting.php 0000666 00000002002 13531431770 0011615 0 ustar 00 input = $input;
$this->output = $output;
$this->command = $command;
}
}
Events/CommandFinished.php 0000666 00000002254 13531431770 0011564 0 ustar 00 input = $input;
$this->output = $output;
$this->command = $command;
$this->exitCode = $exitCode;
}
}
GeneratorCommand.php 0000666 00000014161 13531431770 0010515 0 ustar 00 files = $files;
}
/**
* Get the stub file for the generator.
*
* @return string
*/
abstract protected function getStub();
/**
* Execute the console command.
*
* @return bool|null
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function handle()
{
$name = $this->qualifyClass($this->getNameInput());
$path = $this->getPath($name);
// First we will check to see if the class already exists. If it does, we don't want
// to create the class and overwrite the user's code. So, we will bail out so the
// code is untouched. Otherwise, we will continue generating this class' files.
if ((! $this->hasOption('force') ||
! $this->option('force')) &&
$this->alreadyExists($this->getNameInput())) {
$this->error($this->type.' already exists!');
return false;
}
// Next, we will generate the path to the location where this class' file should get
// written. Then, we will build the class and make the proper replacements on the
// stub files so that it gets the correctly formatted namespace and class name.
$this->makeDirectory($path);
$this->files->put($path, $this->buildClass($name));
$this->info($this->type.' created successfully.');
}
/**
* Parse the class name and format according to the root namespace.
*
* @param string $name
* @return string
*/
protected function qualifyClass($name)
{
$name = ltrim($name, '\\/');
$rootNamespace = $this->rootNamespace();
if (Str::startsWith($name, $rootNamespace)) {
return $name;
}
$name = str_replace('/', '\\', $name);
return $this->qualifyClass(
$this->getDefaultNamespace(trim($rootNamespace, '\\')).'\\'.$name
);
}
/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace;
}
/**
* Determine if the class already exists.
*
* @param string $rawName
* @return bool
*/
protected function alreadyExists($rawName)
{
return $this->files->exists($this->getPath($this->qualifyClass($rawName)));
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
protected function getPath($name)
{
$name = Str::replaceFirst($this->rootNamespace(), '', $name);
return $this->laravel['path'].'/'.str_replace('\\', '/', $name).'.php';
}
/**
* Build the directory for the class if necessary.
*
* @param string $path
* @return string
*/
protected function makeDirectory($path)
{
if (! $this->files->isDirectory(dirname($path))) {
$this->files->makeDirectory(dirname($path), 0777, true, true);
}
return $path;
}
/**
* Build the class with the given name.
*
* @param string $name
* @return string
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
protected function buildClass($name)
{
$stub = $this->files->get($this->getStub());
return $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
}
/**
* Replace the namespace for the given stub.
*
* @param string $stub
* @param string $name
* @return $this
*/
protected function replaceNamespace(&$stub, $name)
{
$stub = str_replace(
['DummyNamespace', 'DummyRootNamespace', 'NamespacedDummyUserModel'],
[$this->getNamespace($name), $this->rootNamespace(), $this->userProviderModel()],
$stub
);
return $this;
}
/**
* Get the full namespace for a given class, without the class name.
*
* @param string $name
* @return string
*/
protected function getNamespace($name)
{
return trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');
}
/**
* Replace the class name for the given stub.
*
* @param string $stub
* @param string $name
* @return string
*/
protected function replaceClass($stub, $name)
{
$class = str_replace($this->getNamespace($name).'\\', '', $name);
return str_replace('DummyClass', $class, $stub);
}
/**
* Get the desired class name from the input.
*
* @return string
*/
protected function getNameInput()
{
return trim($this->argument('name'));
}
/**
* Get the root namespace for the class.
*
* @return string
*/
protected function rootNamespace()
{
return $this->laravel->getNamespace();
}
/**
* Get the model for the default guard's user provider.
*
* @return string|null
*/
protected function userProviderModel()
{
$guard = config('auth.defaults.guard');
$provider = config("auth.guards.{$guard}.provider");
return config("auth.providers.{$provider}.model");
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the class'],
];
}
}
ConfirmableTrait.php 0000666 00000002436 13531431770 0010517 0 ustar 00 getDefaultConfirmCallback() : $callback;
$shouldConfirm = $callback instanceof Closure ? call_user_func($callback) : $callback;
if ($shouldConfirm) {
if ($this->hasOption('force') && $this->option('force')) {
return true;
}
$this->alert($warning);
$confirmed = $this->confirm('Do you really wish to run this command?');
if (! $confirmed) {
$this->comment('Command Cancelled!');
return false;
}
}
return true;
}
/**
* Get the default confirmation callback.
*
* @return \Closure
*/
protected function getDefaultConfirmCallback()
{
return function () {
return $this->getLaravel()->environment() === 'production';
};
}
}
DetectsApplicationNamespace.php 0000666 00000000462 13531431770 0012663 0 ustar 00 getNamespace();
}
}
Application.php 0000666 00000020362 13531431770 0007533 0 ustar 00 laravel = $laravel;
$this->events = $events;
$this->setAutoExit(false);
$this->setCatchExceptions(false);
$this->events->dispatch(new Events\ArtisanStarting($this));
$this->bootstrap();
}
/**
* {@inheritdoc}
*/
public function run(InputInterface $input = null, OutputInterface $output = null)
{
$commandName = $this->getCommandName(
$input = $input ?: new ArgvInput
);
$this->events->dispatch(
new Events\CommandStarting(
$commandName, $input, $output = $output ?: new ConsoleOutput
)
);
$exitCode = parent::run($input, $output);
$this->events->dispatch(
new Events\CommandFinished($commandName, $input, $output, $exitCode)
);
return $exitCode;
}
/**
* Determine the proper PHP executable.
*
* @return string
*/
public static function phpBinary()
{
return ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false));
}
/**
* Determine the proper Artisan executable.
*
* @return string
*/
public static function artisanBinary()
{
return defined('ARTISAN_BINARY') ? ProcessUtils::escapeArgument(ARTISAN_BINARY) : 'artisan';
}
/**
* Format the given command as a fully-qualified executable command.
*
* @param string $string
* @return string
*/
public static function formatCommandString($string)
{
return sprintf('%s %s %s', static::phpBinary(), static::artisanBinary(), $string);
}
/**
* Register a console "starting" bootstrapper.
*
* @param \Closure $callback
* @return void
*/
public static function starting(Closure $callback)
{
static::$bootstrappers[] = $callback;
}
/**
* Bootstrap the console application.
*
* @return void
*/
protected function bootstrap()
{
foreach (static::$bootstrappers as $bootstrapper) {
$bootstrapper($this);
}
}
/**
* Clear the console application bootstrappers.
*
* @return void
*/
public static function forgetBootstrappers()
{
static::$bootstrappers = [];
}
/**
* Run an Artisan console command by name.
*
* @param string $command
* @param array $parameters
* @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
* @return int
*
* @throws \Symfony\Component\Console\Exception\CommandNotFoundException
*/
public function call($command, array $parameters = [], $outputBuffer = null)
{
[$command, $input] = $this->parseCommand($command, $parameters);
if (! $this->has($command)) {
throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $command));
}
return $this->run(
$input, $this->lastOutput = $outputBuffer ?: new BufferedOutput
);
}
/**
* Parse the incoming Artisan command and its input.
*
* @param string $command
* @param array $parameters
* @return array
*/
protected function parseCommand($command, $parameters)
{
if (is_subclass_of($command, SymfonyCommand::class)) {
$callingClass = true;
$command = $this->laravel->make($command)->getName();
}
if (! isset($callingClass) && empty($parameters)) {
$command = $this->getCommandName($input = new StringInput($command));
} else {
array_unshift($parameters, $command);
$input = new ArrayInput($parameters);
}
return [$command, $input ?? null];
}
/**
* Get the output for the last run command.
*
* @return string
*/
public function output()
{
return $this->lastOutput && method_exists($this->lastOutput, 'fetch')
? $this->lastOutput->fetch()
: '';
}
/**
* Add a command to the console.
*
* @param \Symfony\Component\Console\Command\Command $command
* @return \Symfony\Component\Console\Command\Command
*/
public function add(SymfonyCommand $command)
{
if ($command instanceof Command) {
$command->setLaravel($this->laravel);
}
return $this->addToParent($command);
}
/**
* Add the command to the parent instance.
*
* @param \Symfony\Component\Console\Command\Command $command
* @return \Symfony\Component\Console\Command\Command
*/
protected function addToParent(SymfonyCommand $command)
{
return parent::add($command);
}
/**
* Add a command, resolving through the application.
*
* @param string $command
* @return \Symfony\Component\Console\Command\Command
*/
public function resolve($command)
{
return $this->add($this->laravel->make($command));
}
/**
* Resolve an array of commands through the application.
*
* @param array|mixed $commands
* @return $this
*/
public function resolveCommands($commands)
{
$commands = is_array($commands) ? $commands : func_get_args();
foreach ($commands as $command) {
$this->resolve($command);
}
return $this;
}
/**
* Get the default input definition for the application.
*
* This is used to add the --env option to every available command.
*
* @return \Symfony\Component\Console\Input\InputDefinition
*/
protected function getDefaultInputDefinition()
{
return tap(parent::getDefaultInputDefinition(), function ($definition) {
$definition->addOption($this->getEnvironmentOption());
});
}
/**
* Get the global environment option for the definition.
*
* @return \Symfony\Component\Console\Input\InputOption
*/
protected function getEnvironmentOption()
{
$message = 'The environment the command should run under';
return new InputOption('--env', null, InputOption::VALUE_OPTIONAL, $message);
}
/**
* Get the Laravel application instance.
*
* @return \Illuminate\Contracts\Foundation\Application
*/
public function getLaravel()
{
return $this->laravel;
}
}
LICENSE.md 0000666 00000002063 13531431770 0006161 0 ustar 00 The MIT License (MIT)
Copyright (c) Taylor Otwell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
composer.json 0000666 00000002224 13531431770 0007276 0 ustar 00 {
"name": "illuminate/console",
"description": "The Illuminate Console package.",
"license": "MIT",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"require": {
"php": "^7.1.3",
"illuminate/contracts": "5.8.*",
"illuminate/support": "5.8.*",
"symfony/console": "^4.2",
"symfony/process": "^4.2"
},
"autoload": {
"psr-4": {
"Illuminate\\Console\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "5.8-dev"
}
},
"suggest": {
"dragonmantank/cron-expression": "Required to use scheduling component (^2.0).",
"guzzlehttp/guzzle": "Required to use the ping methods on schedules (^6.0).",
"illuminate/filesystem": "Required to use the generator command (5.8.*)"
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}
OutputStyle.php 0000666 00000002747 13531431770 0007620 0 ustar 00 output = $output;
parent::__construct($input, $output);
}
/**
* Returns whether verbosity is quiet (-q).
*
* @return bool
*/
public function isQuiet()
{
return $this->output->isQuiet();
}
/**
* Returns whether verbosity is verbose (-v).
*
* @return bool
*/
public function isVerbose()
{
return $this->output->isVerbose();
}
/**
* Returns whether verbosity is very verbose (-vv).
*
* @return bool
*/
public function isVeryVerbose()
{
return $this->output->isVeryVerbose();
}
/**
* Returns whether verbosity is debug (-vvv).
*
* @return bool
*/
public function isDebug()
{
return $this->output->isDebug();
}
}
Scheduling/Schedule.php 0000666 00000013250 13531431770 0011107 0 ustar 00 timezone = $timezone;
$container = Container::getInstance();
$this->eventMutex = $container->bound(EventMutex::class)
? $container->make(EventMutex::class)
: $container->make(CacheEventMutex::class);
$this->schedulingMutex = $container->bound(SchedulingMutex::class)
? $container->make(SchedulingMutex::class)
: $container->make(CacheSchedulingMutex::class);
}
/**
* Add a new callback event to the schedule.
*
* @param string|callable $callback
* @param array $parameters
* @return \Illuminate\Console\Scheduling\CallbackEvent
*/
public function call($callback, array $parameters = [])
{
$this->events[] = $event = new CallbackEvent(
$this->eventMutex, $callback, $parameters
);
return $event;
}
/**
* Add a new Artisan command event to the schedule.
*
* @param string $command
* @param array $parameters
* @return \Illuminate\Console\Scheduling\Event
*/
public function command($command, array $parameters = [])
{
if (class_exists($command)) {
$command = Container::getInstance()->make($command)->getName();
}
return $this->exec(
Application::formatCommandString($command), $parameters
);
}
/**
* Add a new job callback event to the schedule.
*
* @param object|string $job
* @param string|null $queue
* @param string|null $connection
* @return \Illuminate\Console\Scheduling\CallbackEvent
*/
public function job($job, $queue = null, $connection = null)
{
return $this->call(function () use ($job, $queue, $connection) {
$job = is_string($job) ? resolve($job) : $job;
if ($job instanceof ShouldQueue) {
dispatch($job)
->onConnection($connection ?? $job->connection)
->onQueue($queue ?? $job->queue);
} else {
dispatch_now($job);
}
})->name(is_string($job) ? $job : get_class($job));
}
/**
* Add a new command event to the schedule.
*
* @param string $command
* @param array $parameters
* @return \Illuminate\Console\Scheduling\Event
*/
public function exec($command, array $parameters = [])
{
if (count($parameters)) {
$command .= ' '.$this->compileParameters($parameters);
}
$this->events[] = $event = new Event($this->eventMutex, $command, $this->timezone);
return $event;
}
/**
* Compile parameters for a command.
*
* @param array $parameters
* @return string
*/
protected function compileParameters(array $parameters)
{
return collect($parameters)->map(function ($value, $key) {
if (is_array($value)) {
$value = collect($value)->map(function ($value) {
return ProcessUtils::escapeArgument($value);
})->implode(' ');
} elseif (! is_numeric($value) && ! preg_match('/^(-.$|--.*)/i', $value)) {
$value = ProcessUtils::escapeArgument($value);
}
return is_numeric($key) ? $value : "{$key}={$value}";
})->implode(' ');
}
/**
* Determine if the server is allowed to run this event.
*
* @param \Illuminate\Console\Scheduling\Event $event
* @param \DateTimeInterface $time
* @return bool
*/
public function serverShouldRun(Event $event, DateTimeInterface $time)
{
return $this->schedulingMutex->create($event, $time);
}
/**
* Get all of the events on the schedule that are due.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return \Illuminate\Support\Collection
*/
public function dueEvents($app)
{
return collect($this->events)->filter->isDue($app);
}
/**
* Get all of the events on the schedule.
*
* @return \Illuminate\Console\Scheduling\Event[]
*/
public function events()
{
return $this->events;
}
/**
* Specify the cache store that should be used to store mutexes.
*
* @param string $store
* @return $this
*/
public function useCache($store)
{
if ($this->eventMutex instanceof CacheEventMutex) {
$this->eventMutex->useStore($store);
}
if ($this->schedulingMutex instanceof CacheSchedulingMutex) {
$this->schedulingMutex->useStore($store);
}
return $this;
}
}
Scheduling/EventMutex.php 0000666 00000001255 13531431770 0011461 0 ustar 00 schedule = $schedule;
$this->startedAt = Date::now();
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
foreach ($this->schedule->dueEvents($this->laravel) as $event) {
if (! $event->filtersPass($this->laravel)) {
continue;
}
if ($event->onOneServer) {
$this->runSingleServerEvent($event);
} else {
$this->runEvent($event);
}
$this->eventsRan = true;
}
if (! $this->eventsRan) {
$this->info('No scheduled commands are ready to run.');
}
}
/**
* Run the given single server event.
*
* @param \Illuminate\Console\Scheduling\Event $event
* @return void
*/
protected function runSingleServerEvent($event)
{
if ($this->schedule->serverShouldRun($event, $this->startedAt)) {
$this->runEvent($event);
} else {
$this->line('Skipping command (has already run on another server): '.$event->getSummaryForDisplay());
}
}
/**
* Run the given event.
*
* @param \Illuminate\Console\Scheduling\Event $event
* @return void
*/
protected function runEvent($event)
{
$this->line('Running scheduled command: '.$event->getSummaryForDisplay());
$event->run($this->laravel);
$this->eventsRan = true;
}
}
Scheduling/ScheduleFinishCommand.php 0000666 00000002414 13531431770 0013547 0 ustar 00 schedule = $schedule;
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
collect($this->schedule->events())->filter(function ($value) {
return $value->mutexName() == $this->argument('id');
})->each->callAfterCallbacks($this->laravel);
}
}
Scheduling/SchedulingMutex.php 0000666 00000001222 13531431770 0012457 0 ustar 00 cache = $cache;
}
/**
* Attempt to obtain an event mutex for the given event.
*
* @param \Illuminate\Console\Scheduling\Event $event
* @return bool
*/
public function create(Event $event)
{
return $this->cache->store($this->store)->add(
$event->mutexName(), true, $event->expiresAt * 60
);
}
/**
* Determine if an event mutex exists for the given event.
*
* @param \Illuminate\Console\Scheduling\Event $event
* @return bool
*/
public function exists(Event $event)
{
return $this->cache->store($this->store)->has($event->mutexName());
}
/**
* Clear the event mutex for the given event.
*
* @param \Illuminate\Console\Scheduling\Event $event
* @return void
*/
public function forget(Event $event)
{
$this->cache->store($this->store)->forget($event->mutexName());
}
/**
* Specify the cache store that should be used.
*
* @param string $store
* @return $this
*/
public function useStore($store)
{
$this->store = $store;
return $this;
}
}
Scheduling/CacheSchedulingMutex.php 0000666 00000003257 13531431770 0013415 0 ustar 00 cache = $cache;
}
/**
* Attempt to obtain a scheduling mutex for the given event.
*
* @param \Illuminate\Console\Scheduling\Event $event
* @param \DateTimeInterface $time
* @return bool
*/
public function create(Event $event, DateTimeInterface $time)
{
return $this->cache->store($this->store)->add(
$event->mutexName().$time->format('Hi'), true, 3600
);
}
/**
* Determine if a scheduling mutex exists for the given event.
*
* @param \Illuminate\Console\Scheduling\Event $event
* @param \DateTimeInterface $time
* @return bool
*/
public function exists(Event $event, DateTimeInterface $time)
{
return $this->cache->store($this->store)->has(
$event->mutexName().$time->format('Hi')
);
}
/**
* Specify the cache store that should be used.
*
* @param string $store
* @return $this
*/
public function useStore($store)
{
$this->store = $store;
return $this;
}
}
Scheduling/CommandBuilder.php 0000666 00000004061 13531431770 0012240 0 ustar 00 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().'"';
return $this->ensureCorrectUser($event,
'('.$event->command.$redirect.$output.' 2>&1 '.(windows_os() ? '&' : ';').' '.$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;
}
}
Scheduling/Event.php 0000666 00000044641 13531431770 0010444 0 ustar 00 mutex = $mutex;
$this->command = $command;
$this->timezone = $timezone;
$this->output = $this->getDefaultOutput();
}
/**
* Get the default output depending on the OS.
*
* @return string
*/
public function getDefaultOutput()
{
return (DIRECTORY_SEPARATOR === '\\') ? 'NUL' : '/dev/null';
}
/**
* Run the given event.
*
* @param \Illuminate\Contracts\Container\Container $container
* @return void
*/
public function run(Container $container)
{
if ($this->withoutOverlapping &&
! $this->mutex->create($this)) {
return;
}
$this->runInBackground
? $this->runCommandInBackground($container)
: $this->runCommandInForeground($container);
}
/**
* Get the mutex name for the scheduled command.
*
* @return string
*/
public function mutexName()
{
return 'framework'.DIRECTORY_SEPARATOR.'schedule-'.sha1($this->expression.$this->command);
}
/**
* Run the command in the foreground.
*
* @param \Illuminate\Contracts\Container\Container $container
* @return void
*/
protected function runCommandInForeground(Container $container)
{
$this->callBeforeCallbacks($container);
$this->exitCode = Process::fromShellCommandline($this->buildCommand(), base_path(), null, null, null)->run();
$this->callAfterCallbacks($container);
}
/**
* Run the command in the background.
*
* @param \Illuminate\Contracts\Container\Container $container
* @return void
*/
protected function runCommandInBackground(Container $container)
{
$this->callBeforeCallbacks($container);
Process::fromShellCommandline($this->buildCommand(), base_path(), null, null, null)->run();
}
/**
* Call all of the "before" callbacks for the event.
*
* @param \Illuminate\Contracts\Container\Container $container
* @return void
*/
public function callBeforeCallbacks(Container $container)
{
foreach ($this->beforeCallbacks as $callback) {
$container->call($callback);
}
}
/**
* Call all of the "after" callbacks for the event.
*
* @param \Illuminate\Contracts\Container\Container $container
* @return void
*/
public function callAfterCallbacks(Container $container)
{
foreach ($this->afterCallbacks as $callback) {
$container->call($callback);
}
}
/**
* Build the command string.
*
* @return string
*/
public function buildCommand()
{
return (new CommandBuilder)->buildCommand($this);
}
/**
* Determine if the given event should run based on the Cron expression.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return bool
*/
public function isDue($app)
{
if (! $this->runsInMaintenanceMode() && $app->isDownForMaintenance()) {
return false;
}
return $this->expressionPasses() &&
$this->runsInEnvironment($app->environment());
}
/**
* Determine if the event runs in maintenance mode.
*
* @return bool
*/
public function runsInMaintenanceMode()
{
return $this->evenInMaintenanceMode;
}
/**
* Determine if the Cron expression passes.
*
* @return bool
*/
protected function expressionPasses()
{
$date = Carbon::now();
if ($this->timezone) {
$date->setTimezone($this->timezone);
}
return CronExpression::factory($this->expression)->isDue($date->toDateTimeString());
}
/**
* Determine if the event runs in the given environment.
*
* @param string $environment
* @return bool
*/
public function runsInEnvironment($environment)
{
return empty($this->environments) || in_array($environment, $this->environments);
}
/**
* Determine if the filters pass for the event.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return bool
*/
public function filtersPass($app)
{
foreach ($this->filters as $callback) {
if (! $app->call($callback)) {
return false;
}
}
foreach ($this->rejects as $callback) {
if ($app->call($callback)) {
return false;
}
}
return true;
}
/**
* Ensure that the output is stored on disk in a log file.
*
* @return $this
*/
public function storeOutput()
{
$this->ensureOutputIsBeingCaptured();
return $this;
}
/**
* Send the output of the command to a given location.
*
* @param string $location
* @param bool $append
* @return $this
*/
public function sendOutputTo($location, $append = false)
{
$this->output = $location;
$this->shouldAppendOutput = $append;
return $this;
}
/**
* Append the output of the command to a given location.
*
* @param string $location
* @return $this
*/
public function appendOutputTo($location)
{
return $this->sendOutputTo($location, true);
}
/**
* E-mail the results of the scheduled operation.
*
* @param array|mixed $addresses
* @param bool $onlyIfOutputExists
* @return $this
*
* @throws \LogicException
*/
public function emailOutputTo($addresses, $onlyIfOutputExists = false)
{
$this->ensureOutputIsBeingCaptured();
$addresses = Arr::wrap($addresses);
return $this->then(function (Mailer $mailer) use ($addresses, $onlyIfOutputExists) {
$this->emailOutput($mailer, $addresses, $onlyIfOutputExists);
});
}
/**
* E-mail the results of the scheduled operation if it produces output.
*
* @param array|mixed $addresses
* @return $this
*
* @throws \LogicException
*/
public function emailWrittenOutputTo($addresses)
{
return $this->emailOutputTo($addresses, true);
}
/**
* E-mail the results of the scheduled operation if it fails.
*
* @param array|mixed $addresses
* @return $this
*/
public function emailOutputOnFailure($addresses)
{
$this->ensureOutputIsBeingCaptured();
$addresses = Arr::wrap($addresses);
return $this->onFailure(function (Mailer $mailer) use ($addresses) {
$this->emailOutput($mailer, $addresses, false);
});
}
/**
* Ensure that the command output is being captured.
*
* @return void
*/
protected function ensureOutputIsBeingCaptured()
{
if (is_null($this->output) || $this->output == $this->getDefaultOutput()) {
$this->sendOutputTo(storage_path('logs/schedule-'.sha1($this->mutexName()).'.log'));
}
}
/**
* E-mail the output of the event to the recipients.
*
* @param \Illuminate\Contracts\Mail\Mailer $mailer
* @param array $addresses
* @param bool $onlyIfOutputExists
* @return void
*/
protected function emailOutput(Mailer $mailer, $addresses, $onlyIfOutputExists = false)
{
$text = file_exists($this->output) ? file_get_contents($this->output) : '';
if ($onlyIfOutputExists && empty($text)) {
return;
}
$mailer->raw($text, function ($m) use ($addresses) {
$m->to($addresses)->subject($this->getEmailSubject());
});
}
/**
* Get the e-mail subject line for output results.
*
* @return string
*/
protected function getEmailSubject()
{
if ($this->description) {
return $this->description;
}
return "Scheduled Job Output For [{$this->command}]";
}
/**
* Register a callback to ping a given URL before the job runs.
*
* @param string $url
* @return $this
*/
public function pingBefore($url)
{
return $this->before(function () use ($url) {
(new HttpClient)->get($url);
});
}
/**
* Register a callback to ping a given URL before the job runs if the given condition is true.
*
* @param bool $value
* @param string $url
* @return $this
*/
public function pingBeforeIf($value, $url)
{
return $value ? $this->pingBefore($url) : $this;
}
/**
* Register a callback to ping a given URL after the job runs.
*
* @param string $url
* @return $this
*/
public function thenPing($url)
{
return $this->then(function () use ($url) {
(new HttpClient)->get($url);
});
}
/**
* Register a callback to ping a given URL after the job runs if the given condition is true.
*
* @param bool $value
* @param string $url
* @return $this
*/
public function thenPingIf($value, $url)
{
return $value ? $this->thenPing($url) : $this;
}
/**
* Register a callback to ping a given URL if the operation succeeds.
*
* @param string $url
* @return $this
*/
public function pingOnSuccess($url)
{
return $this->onSuccess(function () use ($url) {
(new HttpClient)->get($url);
});
}
/**
* Register a callback to ping a given URL if the operation fails.
*
* @param string $url
* @return $this
*/
public function pingOnFailure($url)
{
return $this->onFailure(function () use ($url) {
(new HttpClient)->get($url);
});
}
/**
* State that the command should run in background.
*
* @return $this
*/
public function runInBackground()
{
$this->runInBackground = true;
return $this;
}
/**
* Set which user the command should run as.
*
* @param string $user
* @return $this
*/
public function user($user)
{
$this->user = $user;
return $this;
}
/**
* Limit the environments the command should run in.
*
* @param array|mixed $environments
* @return $this
*/
public function environments($environments)
{
$this->environments = is_array($environments) ? $environments : func_get_args();
return $this;
}
/**
* State that the command should run even in maintenance mode.
*
* @return $this
*/
public function evenInMaintenanceMode()
{
$this->evenInMaintenanceMode = true;
return $this;
}
/**
* Do not allow the event to overlap each other.
*
* @param int $expiresAt
* @return $this
*/
public function withoutOverlapping($expiresAt = 1440)
{
$this->withoutOverlapping = true;
$this->expiresAt = $expiresAt;
return $this->then(function () {
$this->mutex->forget($this);
})->skip(function () {
return $this->mutex->exists($this);
});
}
/**
* Allow the event to only run on one server for each cron expression.
*
* @return $this
*/
public function onOneServer()
{
$this->onOneServer = true;
return $this;
}
/**
* Register a callback to further filter the schedule.
*
* @param \Closure|bool $callback
* @return $this
*/
public function when($callback)
{
$this->filters[] = is_callable($callback) ? $callback : function () use ($callback) {
return $callback;
};
return $this;
}
/**
* Register a callback to further filter the schedule.
*
* @param \Closure|bool $callback
* @return $this
*/
public function skip($callback)
{
$this->rejects[] = is_callable($callback) ? $callback : function () use ($callback) {
return $callback;
};
return $this;
}
/**
* Register a callback to be called before the operation.
*
* @param \Closure $callback
* @return $this
*/
public function before(Closure $callback)
{
$this->beforeCallbacks[] = $callback;
return $this;
}
/**
* Register a callback to be called after the operation.
*
* @param \Closure $callback
* @return $this
*/
public function after(Closure $callback)
{
return $this->then($callback);
}
/**
* Register a callback to be called after the operation.
*
* @param \Closure $callback
* @return $this
*/
public function then(Closure $callback)
{
$this->afterCallbacks[] = $callback;
return $this;
}
/**
* Register a callback to be called if the operation succeeds.
*
* @param \Closure $callback
* @return $this
*/
public function onSuccess(Closure $callback)
{
return $this->then(function (Container $container) use ($callback) {
if (0 === $this->exitCode) {
$container->call($callback);
}
});
}
/**
* Register a callback to be called if the operation fails.
*
* @param \Closure $callback
* @return $this
*/
public function onFailure(Closure $callback)
{
return $this->then(function (Container $container) use ($callback) {
if (0 !== $this->exitCode) {
$container->call($callback);
}
});
}
/**
* Set the human-friendly description of the event.
*
* @param string $description
* @return $this
*/
public function name($description)
{
return $this->description($description);
}
/**
* Set the human-friendly description of the event.
*
* @param string $description
* @return $this
*/
public function description($description)
{
$this->description = $description;
return $this;
}
/**
* Get the summary of the event for display.
*
* @return string
*/
public function getSummaryForDisplay()
{
if (is_string($this->description)) {
return $this->description;
}
return $this->buildCommand();
}
/**
* Determine the next due date for an event.
*
* @param \DateTimeInterface|string $currentTime
* @param int $nth
* @param bool $allowCurrentDate
* @return \Illuminate\Support\Carbon
*/
public function nextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
{
return Date::instance(CronExpression::factory(
$this->getExpression()
)->getNextRunDate($currentTime, $nth, $allowCurrentDate, $this->timezone));
}
/**
* Get the Cron expression for the event.
*
* @return string
*/
public function getExpression()
{
return $this->expression;
}
/**
* Set the event mutex implementation to be used.
*
* @param \Illuminate\Console\Scheduling\EventMutex $mutex
* @return $this
*/
public function preventOverlapsUsing(EventMutex $mutex)
{
$this->mutex = $mutex;
return $this;
}
}
Scheduling/CallbackEvent.php 0000666 00000007635 13531431770 0012063 0 ustar 00 mutex = $mutex;
$this->callback = $callback;
$this->parameters = $parameters;
}
/**
* Run the given event.
*
* @param \Illuminate\Contracts\Container\Container $container
* @return mixed
*
* @throws \Exception
*/
public function run(Container $container)
{
if ($this->description && $this->withoutOverlapping &&
! $this->mutex->create($this)) {
return;
}
$pid = getmypid();
register_shutdown_function(function () use ($pid) {
if ($pid === getmypid()) {
$this->removeMutex();
}
});
parent::callBeforeCallbacks($container);
try {
$response = is_object($this->callback)
? $container->call([$this->callback, '__invoke'], $this->parameters)
: $container->call($this->callback, $this->parameters);
} finally {
$this->removeMutex();
parent::callAfterCallbacks($container);
}
return $response;
}
/**
* Clear the mutex for the event.
*
* @return void
*/
protected function removeMutex()
{
if ($this->description && $this->withoutOverlapping) {
$this->mutex->forget($this);
}
}
/**
* Do not allow the event to overlap each other.
*
* @param int $expiresAt
* @return $this
*
* @throws \LogicException
*/
public function withoutOverlapping($expiresAt = 1440)
{
if (! isset($this->description)) {
throw new LogicException(
"A scheduled event name is required to prevent overlapping. Use the 'name' method before 'withoutOverlapping'."
);
}
$this->withoutOverlapping = true;
$this->expiresAt = $expiresAt;
return $this->skip(function () {
return $this->mutex->exists($this);
});
}
/**
* Allow the event to only run on one server for each cron expression.
*
* @return $this
*
* @throws \LogicException
*/
public function onOneServer()
{
if (! isset($this->description)) {
throw new LogicException(
"A scheduled event name is required to only run on one server. Use the 'name' method before 'onOneServer'."
);
}
$this->onOneServer = true;
return $this;
}
/**
* Get the mutex name for the scheduled command.
*
* @return string
*/
public function mutexName()
{
return 'framework/schedule-'.sha1($this->description);
}
/**
* Get the summary of the event for display.
*
* @return string
*/
public function getSummaryForDisplay()
{
if (is_string($this->description)) {
return $this->description;
}
return is_string($this->callback) ? $this->callback : 'Closure';
}
}
Scheduling/ManagesFrequencies.php 0000666 00000021341 13531431770 0013120 0 ustar 00 expression = $expression;
return $this;
}
/**
* Schedule the event to run between start and end time.
*
* @param string $startTime
* @param string $endTime
* @return $this
*/
public function between($startTime, $endTime)
{
return $this->when($this->inTimeInterval($startTime, $endTime));
}
/**
* Schedule the event to not run between start and end time.
*
* @param string $startTime
* @param string $endTime
* @return $this
*/
public function unlessBetween($startTime, $endTime)
{
return $this->skip($this->inTimeInterval($startTime, $endTime));
}
/**
* Schedule the event to run between start and end time.
*
* @param string $startTime
* @param string $endTime
* @return \Closure
*/
private function inTimeInterval($startTime, $endTime)
{
return function () use ($startTime, $endTime) {
return Carbon::now($this->timezone)->between(
Carbon::parse($startTime, $this->timezone),
Carbon::parse($endTime, $this->timezone),
true
);
};
}
/**
* Schedule the event to run every minute.
*
* @return $this
*/
public function everyMinute()
{
return $this->spliceIntoPosition(1, '*');
}
/**
* Schedule the event to run every five minutes.
*
* @return $this
*/
public function everyFiveMinutes()
{
return $this->spliceIntoPosition(1, '*/5');
}
/**
* Schedule the event to run every ten minutes.
*
* @return $this
*/
public function everyTenMinutes()
{
return $this->spliceIntoPosition(1, '*/10');
}
/**
* Schedule the event to run every fifteen minutes.
*
* @return $this
*/
public function everyFifteenMinutes()
{
return $this->spliceIntoPosition(1, '*/15');
}
/**
* Schedule the event to run every thirty minutes.
*
* @return $this
*/
public function everyThirtyMinutes()
{
return $this->spliceIntoPosition(1, '0,30');
}
/**
* Schedule the event to run hourly.
*
* @return $this
*/
public function hourly()
{
return $this->spliceIntoPosition(1, 0);
}
/**
* Schedule the event to run hourly at a given offset in the hour.
*
* @param array|int $offset
* @return $this
*/
public function hourlyAt($offset)
{
$offset = is_array($offset) ? implode(',', $offset) : $offset;
return $this->spliceIntoPosition(1, $offset);
}
/**
* Schedule the event to run daily.
*
* @return $this
*/
public function daily()
{
return $this->spliceIntoPosition(1, 0)
->spliceIntoPosition(2, 0);
}
/**
* Schedule the command at a given time.
*
* @param string $time
* @return $this
*/
public function at($time)
{
return $this->dailyAt($time);
}
/**
* Schedule the event to run daily at a given time (10:00, 19:30, etc).
*
* @param string $time
* @return $this
*/
public function dailyAt($time)
{
$segments = explode(':', $time);
return $this->spliceIntoPosition(2, (int) $segments[0])
->spliceIntoPosition(1, count($segments) === 2 ? (int) $segments[1] : '0');
}
/**
* Schedule the event to run twice daily.
*
* @param int $first
* @param int $second
* @return $this
*/
public function twiceDaily($first = 1, $second = 13)
{
$hours = $first.','.$second;
return $this->spliceIntoPosition(1, 0)
->spliceIntoPosition(2, $hours);
}
/**
* Schedule the event to run only on weekdays.
*
* @return $this
*/
public function weekdays()
{
return $this->spliceIntoPosition(5, '1-5');
}
/**
* Schedule the event to run only on weekends.
*
* @return $this
*/
public function weekends()
{
return $this->spliceIntoPosition(5, '0,6');
}
/**
* Schedule the event to run only on Mondays.
*
* @return $this
*/
public function mondays()
{
return $this->days(1);
}
/**
* Schedule the event to run only on Tuesdays.
*
* @return $this
*/
public function tuesdays()
{
return $this->days(2);
}
/**
* Schedule the event to run only on Wednesdays.
*
* @return $this
*/
public function wednesdays()
{
return $this->days(3);
}
/**
* Schedule the event to run only on Thursdays.
*
* @return $this
*/
public function thursdays()
{
return $this->days(4);
}
/**
* Schedule the event to run only on Fridays.
*
* @return $this
*/
public function fridays()
{
return $this->days(5);
}
/**
* Schedule the event to run only on Saturdays.
*
* @return $this
*/
public function saturdays()
{
return $this->days(6);
}
/**
* Schedule the event to run only on Sundays.
*
* @return $this
*/
public function sundays()
{
return $this->days(0);
}
/**
* Schedule the event to run weekly.
*
* @return $this
*/
public function weekly()
{
return $this->spliceIntoPosition(1, 0)
->spliceIntoPosition(2, 0)
->spliceIntoPosition(5, 0);
}
/**
* Schedule the event to run weekly on a given day and time.
*
* @param int $day
* @param string $time
* @return $this
*/
public function weeklyOn($day, $time = '0:0')
{
$this->dailyAt($time);
return $this->spliceIntoPosition(5, $day);
}
/**
* Schedule the event to run monthly.
*
* @return $this
*/
public function monthly()
{
return $this->spliceIntoPosition(1, 0)
->spliceIntoPosition(2, 0)
->spliceIntoPosition(3, 1);
}
/**
* Schedule the event to run monthly on a given day and time.
*
* @param int $day
* @param string $time
* @return $this
*/
public function monthlyOn($day = 1, $time = '0:0')
{
$this->dailyAt($time);
return $this->spliceIntoPosition(3, $day);
}
/**
* Schedule the event to run twice monthly.
*
* @param int $first
* @param int $second
* @return $this
*/
public function twiceMonthly($first = 1, $second = 16)
{
$days = $first.','.$second;
return $this->spliceIntoPosition(1, 0)
->spliceIntoPosition(2, 0)
->spliceIntoPosition(3, $days);
}
/**
* Schedule the event to run quarterly.
*
* @return $this
*/
public function quarterly()
{
return $this->spliceIntoPosition(1, 0)
->spliceIntoPosition(2, 0)
->spliceIntoPosition(3, 1)
->spliceIntoPosition(4, '1-12/3');
}
/**
* Schedule the event to run yearly.
*
* @return $this
*/
public function yearly()
{
return $this->spliceIntoPosition(1, 0)
->spliceIntoPosition(2, 0)
->spliceIntoPosition(3, 1)
->spliceIntoPosition(4, 1);
}
/**
* Set the days of the week the command should run on.
*
* @param array|mixed $days
* @return $this
*/
public function days($days)
{
$days = is_array($days) ? $days : func_get_args();
return $this->spliceIntoPosition(5, implode(',', $days));
}
/**
* Set the timezone the date should be evaluated on.
*
* @param \DateTimeZone|string $timezone
* @return $this
*/
public function timezone($timezone)
{
$this->timezone = $timezone;
return $this;
}
/**
* Splice the given value into the given position of the expression.
*
* @param int $position
* @param string $value
* @return $this
*/
protected function spliceIntoPosition($position, $value)
{
$segments = explode(' ', $this->expression);
$segments[$position - 1] = $value;
return $this->cron(implode(' ', $segments));
}
}
Command.php 0000666 00000037240 13531431770 0006651 0 ustar 00 OutputInterface::VERBOSITY_VERBOSE,
'vv' => OutputInterface::VERBOSITY_VERY_VERBOSE,
'vvv' => OutputInterface::VERBOSITY_DEBUG,
'quiet' => OutputInterface::VERBOSITY_QUIET,
'normal' => OutputInterface::VERBOSITY_NORMAL,
];
/**
* Create a new console command instance.
*
* @return void
*/
public function __construct()
{
// We will go ahead and set the name, description, and parameters on console
// commands just to make things a little easier on the developer. This is
// so they don't have to all be manually specified in the constructors.
if (isset($this->signature)) {
$this->configureUsingFluentDefinition();
} else {
parent::__construct($this->name);
}
// Once we have constructed the command, we'll set the description and other
// related properties of the command. If a signature wasn't used to build
// the command we'll set the arguments and the options on this command.
$this->setDescription($this->description);
$this->setHidden($this->isHidden());
if (! isset($this->signature)) {
$this->specifyParameters();
}
}
/**
* Configure the console command using a fluent definition.
*
* @return void
*/
protected function configureUsingFluentDefinition()
{
[$name, $arguments, $options] = Parser::parse($this->signature);
parent::__construct($this->name = $name);
// After parsing the signature we will spin through the arguments and options
// and set them on this command. These will already be changed into proper
// instances of these "InputArgument" and "InputOption" Symfony classes.
$this->getDefinition()->addArguments($arguments);
$this->getDefinition()->addOptions($options);
}
/**
* Specify the arguments and options on the command.
*
* @return void
*/
protected function specifyParameters()
{
// We will loop through all of the arguments and options for the command and
// set them all on the base command instance. This specifies what can get
// passed into these commands as "parameters" to control the execution.
foreach ($this->getArguments() as $arguments) {
call_user_func_array([$this, 'addArgument'], $arguments);
}
foreach ($this->getOptions() as $options) {
call_user_func_array([$this, 'addOption'], $options);
}
}
/**
* Run the console command.
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return int
*/
public function run(InputInterface $input, OutputInterface $output)
{
$this->output = $this->laravel->make(
OutputStyle::class, ['input' => $input, 'output' => $output]
);
return parent::run(
$this->input = $input, $this->output
);
}
/**
* Execute the console command.
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return mixed
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
return $this->laravel->call([$this, 'handle']);
}
/**
* Call another console command.
*
* @param string $command
* @param array $arguments
* @return int
*/
public function call($command, array $arguments = [])
{
$arguments['command'] = $command;
return $this->getApplication()->find($command)->run(
$this->createInputFromArguments($arguments), $this->output
);
}
/**
* Call another console command silently.
*
* @param string $command
* @param array $arguments
* @return int
*/
public function callSilent($command, array $arguments = [])
{
$arguments['command'] = $command;
return $this->getApplication()->find($command)->run(
$this->createInputFromArguments($arguments), new NullOutput
);
}
/**
* Create an input instance from the given arguments.
*
* @param array $arguments
* @return \Symfony\Component\Console\Input\ArrayInput
*/
protected function createInputFromArguments(array $arguments)
{
return tap(new ArrayInput(array_merge($this->context(), $arguments)), function ($input) {
if ($input->hasParameterOption(['--no-interaction'], true)) {
$input->setInteractive(false);
}
});
}
/**
* Get all of the context passed to the command.
*
* @return array
*/
protected function context()
{
return collect($this->option())->only([
'ansi',
'no-ansi',
'no-interaction',
'quiet',
'verbose',
])->filter()->mapWithKeys(function ($value, $key) {
return ["--{$key}" => $value];
})->all();
}
/**
* Determine if the given argument is present.
*
* @param string|int $name
* @return bool
*/
public function hasArgument($name)
{
return $this->input->hasArgument($name);
}
/**
* Get the value of a command argument.
*
* @param string|null $key
* @return string|array|null
*/
public function argument($key = null)
{
if (is_null($key)) {
return $this->input->getArguments();
}
return $this->input->getArgument($key);
}
/**
* Get all of the arguments passed to the command.
*
* @return array
*/
public function arguments()
{
return $this->argument();
}
/**
* Determine if the given option is present.
*
* @param string $name
* @return bool
*/
public function hasOption($name)
{
return $this->input->hasOption($name);
}
/**
* Get the value of a command option.
*
* @param string|null $key
* @return string|array|bool|null
*/
public function option($key = null)
{
if (is_null($key)) {
return $this->input->getOptions();
}
return $this->input->getOption($key);
}
/**
* Get all of the options passed to the command.
*
* @return array
*/
public function options()
{
return $this->option();
}
/**
* Confirm a question with the user.
*
* @param string $question
* @param bool $default
* @return bool
*/
public function confirm($question, $default = false)
{
return $this->output->confirm($question, $default);
}
/**
* Prompt the user for input.
*
* @param string $question
* @param string|null $default
* @return mixed
*/
public function ask($question, $default = null)
{
return $this->output->ask($question, $default);
}
/**
* Prompt the user for input with auto completion.
*
* @param string $question
* @param array $choices
* @param string|null $default
* @return mixed
*/
public function anticipate($question, array $choices, $default = null)
{
return $this->askWithCompletion($question, $choices, $default);
}
/**
* Prompt the user for input with auto completion.
*
* @param string $question
* @param array $choices
* @param string|null $default
* @return mixed
*/
public function askWithCompletion($question, array $choices, $default = null)
{
$question = new Question($question, $default);
$question->setAutocompleterValues($choices);
return $this->output->askQuestion($question);
}
/**
* Prompt the user for input but hide the answer from the console.
*
* @param string $question
* @param bool $fallback
* @return mixed
*/
public function secret($question, $fallback = true)
{
$question = new Question($question);
$question->setHidden(true)->setHiddenFallback($fallback);
return $this->output->askQuestion($question);
}
/**
* Give the user a single choice from an array of answers.
*
* @param string $question
* @param array $choices
* @param string|null $default
* @param mixed|null $attempts
* @param bool|null $multiple
* @return string
*/
public function choice($question, array $choices, $default = null, $attempts = null, $multiple = null)
{
$question = new ChoiceQuestion($question, $choices, $default);
$question->setMaxAttempts($attempts)->setMultiselect($multiple);
return $this->output->askQuestion($question);
}
/**
* Format input to textual table.
*
* @param array $headers
* @param \Illuminate\Contracts\Support\Arrayable|array $rows
* @param string $tableStyle
* @param array $columnStyles
* @return void
*/
public function table($headers, $rows, $tableStyle = 'default', array $columnStyles = [])
{
$table = new Table($this->output);
if ($rows instanceof Arrayable) {
$rows = $rows->toArray();
}
$table->setHeaders((array) $headers)->setRows($rows)->setStyle($tableStyle);
foreach ($columnStyles as $columnIndex => $columnStyle) {
$table->setColumnStyle($columnIndex, $columnStyle);
}
$table->render();
}
/**
* Write a string as information output.
*
* @param string $string
* @param int|string|null $verbosity
* @return void
*/
public function info($string, $verbosity = null)
{
$this->line($string, 'info', $verbosity);
}
/**
* Write a string as standard output.
*
* @param string $string
* @param string|null $style
* @param int|string|null $verbosity
* @return void
*/
public function line($string, $style = null, $verbosity = null)
{
$styled = $style ? "<$style>$string$style>" : $string;
$this->output->writeln($styled, $this->parseVerbosity($verbosity));
}
/**
* Write a string as comment output.
*
* @param string $string
* @param int|string|null $verbosity
* @return void
*/
public function comment($string, $verbosity = null)
{
$this->line($string, 'comment', $verbosity);
}
/**
* Write a string as question output.
*
* @param string $string
* @param int|string|null $verbosity
* @return void
*/
public function question($string, $verbosity = null)
{
$this->line($string, 'question', $verbosity);
}
/**
* Write a string as error output.
*
* @param string $string
* @param int|string|null $verbosity
* @return void
*/
public function error($string, $verbosity = null)
{
$this->line($string, 'error', $verbosity);
}
/**
* Write a string as warning output.
*
* @param string $string
* @param int|string|null $verbosity
* @return void
*/
public function warn($string, $verbosity = null)
{
if (! $this->output->getFormatter()->hasStyle('warning')) {
$style = new OutputFormatterStyle('yellow');
$this->output->getFormatter()->setStyle('warning', $style);
}
$this->line($string, 'warning', $verbosity);
}
/**
* Write a string in an alert box.
*
* @param string $string
* @return void
*/
public function alert($string)
{
$length = Str::length(strip_tags($string)) + 12;
$this->comment(str_repeat('*', $length));
$this->comment('* '.$string.' *');
$this->comment(str_repeat('*', $length));
$this->output->newLine();
}
/**
* Set the verbosity level.
*
* @param string|int $level
* @return void
*/
protected function setVerbosity($level)
{
$this->verbosity = $this->parseVerbosity($level);
}
/**
* Get the verbosity level in terms of Symfony's OutputInterface level.
*
* @param string|int|null $level
* @return int
*/
protected function parseVerbosity($level = null)
{
if (isset($this->verbosityMap[$level])) {
$level = $this->verbosityMap[$level];
} elseif (! is_int($level)) {
$level = $this->verbosity;
}
return $level;
}
/**
* {@inheritdoc}
*/
public function isHidden()
{
return $this->hidden;
}
/**
* {@inheritdoc}
*/
public function setHidden($hidden)
{
parent::setHidden($this->hidden = $hidden);
return $this;
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [];
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return [];
}
/**
* Get the output implementation.
*
* @return \Illuminate\Console\OutputStyle
*/
public function getOutput()
{
return $this->output;
}
/**
* Get the Laravel application instance.
*
* @return \Illuminate\Contracts\Foundation\Application
*/
public function getLaravel()
{
return $this->laravel;
}
/**
* Set the Laravel application instance.
*
* @param \Illuminate\Contracts\Container\Container $laravel
* @return void
*/
public function setLaravel($laravel)
{
$this->laravel = $laravel;
}
}