View source
<?php
namespace Drupal\build_hooks;
use Drupal\build_hooks\Event\BuildTrigger;
use Drupal\build_hooks\Entity\FrontendEnvironmentInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationManager;
use Drupal\build_hooks\Event\ResponseEvent;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class Trigger implements TriggerInterface {
use MessengerTrait;
use StringTranslationTrait;
protected $configFactory;
protected $httpClient;
protected $currentUser;
protected $stringTranslation;
protected $messenger;
protected $logger;
protected $deployLogger;
protected $entityTypeManager;
protected $cacheTagInvalidator;
protected $eventDispatcher;
public function __construct(ConfigFactoryInterface $configFactory, ClientInterface $httpClient, AccountProxyInterface $currentUser, TranslationManager $stringTranslation, MessengerInterface $messenger, LoggerChannelFactoryInterface $logger, DeployLogger $deployLogger, EntityTypeManager $entityTypeManager, CacheTagsInvalidatorInterface $cacheTagInvalidator, EventDispatcherInterface $event_dispatcher) {
$this->configFactory = $configFactory;
$this->httpClient = $httpClient;
$this->currentUser = $currentUser;
$this->stringTranslation = $stringTranslation;
$this->messenger = $messenger;
$this->logger = $logger;
$this->deployLogger = $deployLogger;
$this->entityTypeManager = $entityTypeManager;
$this->cacheTagInvalidator = $cacheTagInvalidator;
$this->eventDispatcher = $event_dispatcher;
}
public function deployFrontendCronEnvironments() {
$this
->deployEnvironmentsByDeploymentStrategy(TriggerInterface::DEPLOYMENT_STRATEGY_CRON);
}
public function deployFrontendEntityUpdateEnvironments() {
$this
->deployEnvironmentsByDeploymentStrategy(TriggerInterface::DEPLOYMENT_STRATEGY_ENTITYSAVE);
}
private function deployEnvironmentsByDeploymentStrategy(string $strategy) {
try {
$environments = $this->entityTypeManager
->getStorage('frontend_environment')
->loadByProperties([
'deployment_strategy' => $strategy,
]);
foreach ($environments as $environment) {
$this
->triggerBuildHookForEnvironment($environment);
}
} catch (\Exception $e) {
$this
->messenger()
->addWarning($this
->t('Could not trigger deployments with strategy @strategy. Error message: @error', [
'@strategy' => $strategy,
'@error' => $e
->getMessage(),
]));
}
}
public function showMenu() {
if (!$this
->isValidUser()) {
return FALSE;
}
return TRUE;
}
private function isValidUser() {
return $this->currentUser
->hasPermission('trigger deployments');
}
public function triggerBuildHookForEnvironment(FrontendEnvironmentInterface $frontendEnvironment) {
$plugin = $frontendEnvironment
->getPlugin();
$buildHookDetails = $plugin
->getBuildHookDetails();
try {
$result = $this
->triggerBuildHook($buildHookDetails, $frontendEnvironment);
if (!$result
->shouldBuild()) {
$reason = $result
->getReason();
$this->messenger
->addWarning($reason);
$this->logger
->get('build_hooks')
->notice(sprintf('Build was cancelled: %s', (string) $reason));
return;
}
if ($plugin
->deploymentWasTriggered($result
->getResponse())) {
$this->deployLogger
->setLastDeployTimeForEnvironment($frontendEnvironment);
$this
->messenger()
->addMessage($this
->t('Deployment triggered for environment @env .', [
'@env' => $frontendEnvironment
->label(),
]));
$this
->invalidateToolbarCacheTag();
}
else {
$this
->messenger()
->addWarning($result
->getResponse()
->getReasonPhrase());
}
} catch (GuzzleException $e) {
$error = [
'Failed to execute build hook for environment @env . Error message: <pre> @message </pre>',
[
'@message' => $e
->getMessage(),
'@env' => $frontendEnvironment
->label(),
],
];
$this
->messenger()
->addError($this
->t('Failed to execute build hook for environment @env . Error message: <pre> @message </pre>', $error[1]));
$this->logger
->get('build_hooks')
->error($error[0], $error[1]);
}
}
private function triggerBuildHook(BuildHookDetails $buildHookDetails, FrontendEnvironmentInterface $frontendEnvironment) {
$deployment_storage = $this->entityTypeManager
->getStorage('build_hooks_deployment');
$deployment = $deployment_storage
->getOrCreateNextDeploymentForEnvironment($frontendEnvironment);
$triggerEvent = new BuildTrigger($buildHookDetails, $frontendEnvironment, $deployment);
$frontendEnvironment
->getPlugin()
->preDeploymentTrigger($triggerEvent);
$this->eventDispatcher
->dispatch(BuildTrigger::class, $triggerEvent);
if (!$triggerEvent
->shouldBuild()) {
return $triggerEvent;
}
$response = $this->httpClient
->request($buildHookDetails
->getMethod(), $buildHookDetails
->getUrl(), $buildHookDetails
->getOptions());
$event = new ResponseEvent($response, $frontendEnvironment
->getPlugin());
$this->eventDispatcher
->dispatch(ResponseEvent::EVENT_NAME, $event);
return $triggerEvent
->setResponse($response);
}
public function getToolbarCacheTag() {
return TriggerInterface::BUILD_HOOKS_TOOLBAR_CACHE_TAG;
}
public function invalidateToolbarCacheTag() {
$this->cacheTagInvalidator
->invalidateTags([
$this
->getToolbarCacheTag(),
]);
}
}