webworld888/app/Http/Controllers/ArtisanBackgroundHelper.php
2021-10-26 19:14:12 +09:00

136 lines
3.9 KiB
PHP

<?php
/**
* ArtisanBackgroundHelper.php
*
* PHP version 7
*
* @category Commands
* @package App\Console\Commands
* @author XE Developers <developers@xpressengine.com>
* @copyright 2020 Copyright XEHub Corp. <https://www.xehub.io>
* @license http://www.gnu.org/licenses/lgpl-3.0-standalone.html LGPL
* @link https://xpressengine.io
*/
namespace App\Http\Controllers;
use Illuminate\Console\Application;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\ProcessUtils;
use Illuminate\Support\Str;
use phpseclib\Net\SSH2;
use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Process;
/**
* Trait ArtisanBackgroundHelper
*
* @category Commands
* @package App\Console\Commands
* @author XE Developers <developers@xpressengine.com>
* @copyright 2020 Copyright XEHub Corp. <https://www.xehub.io>
* @license http://www.gnu.org/licenses/lgpl-3.0-standalone.html LGPL
* @link https://xpressengine.io
*/
trait ArtisanBackgroundHelper
{
/**
* Determine if the php binary is available
*
* @return bool
*/
public function availableProcess()
{
return Application::phpBinary() !== false && app('config')->get('xe.console_allow_url_fopen');
}
/**
* Run artisan command
*
* @param string $command artisan command
* @param array $parameters parameters
* @param callable $callback callback
* @return void
*/
public function runArtisan($command, $parameters = [], callable $callback = null)
{
app()->terminating(function () use ($command, $parameters, $callback) {
$result = $this->availableProcess() ?
$this->runByProcess($command, $parameters) :
$this->runByApp($command, $parameters);
if ($callback) {
call_user_func($callback, $result, $command, $parameters);
}
});
}
/**
* Run artisan command on application
*
* @param string $command artisan command
* @param array $parameters parameters
* @return int
*/
protected function runByApp($command, array $parameters)
{
ignore_user_abort(true);
return Artisan::call($command, $parameters);
}
/**
* Run artisan command by the process
*
* @param string $command artisan command
* @param array $parameters parameters
* @return int
*/
protected function runByProcess($command, array $parameters)
{
$commands = [$command];
foreach ($parameters as $key => $value) {
if (is_array($value)) {
$commands = array_merge($commands, array_map(function ($item) use ($key) {
return $this->buildProcessParameter($key, $item);
}, $value));
} else {
$commands[] = $this->buildProcessParameter($key, $value);
}
}
$commandLine = Application::formatCommandString(implode(' ', array_filter($commands)));
if (windows_os()) {
$commandLine = 'start "" ' . $commandLine;
} else {
$commandLine = $commandLine . ' 2>&1 &';
}
try {
return (new Process($commandLine, base_path(), null, null, 3))->run();
} catch (ProcessTimedOutException $e) {
// not throw exception
return 0;
}
}
/**
* Build the parameter for the process
*
* @param string $key parameter key
* @param mixed $value parameter value
* @return int|null|string
*/
protected function buildProcessParameter($key, $value)
{
if (is_bool($value)) {
return $value === true ? $key : null;
}
$escaped = is_int($value) ? $value : ProcessUtils::escapeArgument($value);
return Str::startsWith($key, '-') ? $key.'='.$escaped : $escaped;
}
}