View source
<?php
namespace Drupal\acsf_sj\Api;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Process\Process;
class SjApiClient implements SjClientInterface {
protected $domain;
protected $logger;
private $binary;
public function __construct(RequestStack $request_stack, LoggerInterface $logger) {
$this->domain = $request_stack
->getCurrentRequest()
->getHost();
$this->logger = $logger;
$this->binary = acsf_sj_get_sjadd_path();
}
public function addJob($drush_command, $reason = NULL, $timestamp = NULL, $domain = NULL, $timeout = NULL, $drush_executable = NULL, $drush_options = NULL) {
try {
$this
->inputValidation($drush_command, $timestamp, $domain, $timeout, $drush_executable, $drush_options);
} catch (\Exception $e) {
$this->logger
->log(LogLevel::ERROR, 'Unable to add the scheduled job: @message', [
'@message' => $e
->getMessage(),
]);
return FALSE;
}
$sjadd_arguments = $this
->prepareCommandArguments($drush_command, $reason, $timestamp, $domain, $timeout, $drush_executable, $drush_options);
return $this
->executeSjAdd($sjadd_arguments);
}
protected function inputValidation($drush_command, &$timestamp, &$domain, $timeout = NULL, &$drush_executable = NULL, &$drush_options = NULL) {
if (is_null($timestamp)) {
$timestamp = time();
}
$domain = !empty($domain) ? $domain : $this->domain;
$drush_executable = !empty($drush_executable) ? $drush_executable : 'drush';
if (is_null($drush_options)) {
$drush_options = '-y';
}
if (empty($drush_command) || !is_string($drush_command)) {
throw new \InvalidArgumentException('The command argument must be a non-empty string.');
}
if (!is_numeric($timestamp) || intval($timestamp) < 0) {
throw new \InvalidArgumentException('The timestamp argument must be a positive integer.');
}
if (!is_null($domain) && (empty($domain) || !is_string($domain))) {
throw new \InvalidArgumentException('The domain argument must be a non-empty string.');
}
if (!is_null($timeout) && (!is_numeric($timeout) || intval($timeout) < 0)) {
throw new \InvalidArgumentException('The timeout argument must be a positive integer.');
}
if (!is_null($drush_executable) && (empty($drush_executable) || !is_string($drush_executable))) {
throw new \InvalidArgumentException('The drush_executable argument must be a non-empty string.');
}
if (empty($drush_options) || !is_string($drush_options)) {
throw new \InvalidArgumentException('The drush_options argument must be a non-empty string.');
}
}
protected function prepareCommandArguments($drush_command, $reason, $timestamp, $domain, $timeout, $drush_executable, $drush_options) {
$arguments = '';
if (!empty($reason)) {
$arguments .= sprintf('--reason=%s ', escapeshellarg($reason));
}
if (!empty($timeout) && is_numeric($timeout)) {
$arguments .= sprintf('--max-exec-time=%ds ', $timeout);
}
$arguments .= sprintf('%d %s %s %s %s', intval($timestamp), escapeshellarg($domain), escapeshellarg($drush_command), escapeshellarg($drush_executable), escapeshellarg($drush_options));
return $arguments;
}
private function executeSjAdd($command_arguments) {
$error = '';
if (!$this->binary) {
$error = "The installation path for the ACSF 'sjadd' binary cannot be determined.";
}
elseif (!is_executable($this->binary)) {
$error = "The ACSF 'sjadd' binary is missing or not executable, preventing adding a scheduled job.";
}
$exit_code = -1;
if (!$error) {
$command = sprintf('%s %s', $this->binary, $command_arguments);
for ($retry = 0; $retry < 2 && $exit_code !== 0; $retry++) {
if ($retry) {
$this->logger
->log(LogLevel::WARNING, "Command '@command' will be re-run; it exited with code @code:\n@error", [
'@command' => $command,
'@code' => $exit_code,
'@error' => $error,
]);
usleep(500000);
}
try {
$process = new Process($command);
$process
->setTimeout(10);
$process
->run();
$exit_code = $process
->getExitCode();
if ($exit_code !== 0) {
$error = $process
->getErrorOutput();
}
} catch (\Exception $e) {
$error = $e
->getMessage();
}
}
}
if ($exit_code !== 0) {
$this->logger
->log(LogLevel::ERROR, "Command '@command' exited with code @code:\n@error", [
'@command' => $command ?? '-',
'@code' => $exit_code,
'@error' => $error,
]);
}
return $exit_code === 0;
}
}