View source
<?php
namespace Drupal\deploy\Entity\Form;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Url;
use Drupal\replication\Entity\ReplicationLogInterface;
use Drupal\workspace\Entity\Replication;
use Drupal\workspace\WorkspacePointerInterface;
class ReplicationForm extends ContentEntityForm {
protected $source = NULL;
protected $target = NULL;
public function addTitle() {
$this
->setEntity(Replication::create());
if (!$this
->getDefaultSource() || !$this
->getDefaultTarget()) {
return $this
->t('Error');
}
$target = $this
->getDefaultTarget();
$remote_name = '';
if (!empty($target->remote_database->value) && !empty($target->remote_pointer->entity)) {
$target_workspace_name = $target->remote_database->value;
$remote_name = $target->remote_pointer->entity
->label();
$target_workspace_name = ucfirst($target_workspace_name);
$message = 'Deploy changes from local @source workspace to @target workspace on @remote';
}
else {
$target_workspace_name = $this
->getDefaultTarget()
->label();
$message = 'Deploy changes from local @source workspace to @target workspace';
}
return $this
->t($message, [
'@source' => $this
->getDefaultSource()
->label(),
'@target' => $target_workspace_name,
'@remote' => $remote_name,
]);
}
public function buildForm(array $form, FormStateInterface $form_state) {
$input = $form_state
->getUserInput();
$js = isset($input['_drupal_ajax']) ? TRUE : FALSE;
$form = parent::buildForm($form, $form_state);
$default_source = $this
->getDefaultSource();
$default_target = $this
->getDefaultTarget();
$published = NULL;
if ($target_workspace = $default_target
->get('workspace_pointer')->entity) {
$published = $target_workspace
->isPublished();
}
if (!$default_source || !$default_target || $published === FALSE) {
$message = $this
->t('Source and target must be set, make sure your current workspace has an upstream. Go to <a href=":path">this page</a> to edit your workspaces.', [
':path' => Url::fromRoute('entity.workspace.collection')
->toString(),
]);
if ($js) {
return [
'#markup' => $message,
];
}
$this
->messenger()
->addError($message);
return [];
}
$this->conflictTracker = \Drupal::service('workspace.conflict_tracker');
$source_workspace = $default_source
->getWorkspace();
$conflicts = $this->conflictTracker
->useWorkspace($source_workspace)
->getAll();
if ($conflicts) {
$form['message'] = $this
->generateMessageRenderArray('error', $this
->t('There are <a href=":link">@count conflict(s) with the :target workspace</a>. Pushing changes to :target may result in unexpected behavior or data loss, and cannot be undone. Please proceed with caution.', [
'@count' => count($conflicts),
':link' => Url::fromRoute('entity.workspace.conflicts', [
'workspace' => $source_workspace
->id(),
])
->toString(),
':target' => $default_target
->label(),
]));
$form['is_aborted_on_conflict'] = [
'#type' => 'radios',
'#title' => $this
->t('Abort if there are conflicts?'),
'#default_value' => 'true',
'#options' => [
'true' => $this
->t('Yes, if conflicts are found do not replicate to upstream.'),
'false' => $this
->t('No, go ahead and push any conflicts to the upstream.'),
],
'#weight' => 0,
];
}
else {
$form['message'] = $this
->generateMessageRenderArray('status', 'There are no conflicts.');
}
if (!$source_workspace
->isDefaultWorkspace()) {
$form['archive'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Archive workspace after deployment'),
'#description' => $this
->t('The workspace will be archived only if the deployment finishes with success.'),
'#default_value' => FALSE,
];
}
$form['source']['widget']['#default_value'] = [
$default_source
->id(),
];
if (empty($this->entity
->get('target')->target_id) && $default_target) {
$form['target']['widget']['#default_value'] = [
$default_target
->id(),
];
}
if (!$form['source']['#access'] && !$form['target']['#access']) {
$form['actions']['submit']['#value'] = $this
->t('Deploy to @target', [
'@target' => $default_target
->label(),
]);
}
else {
$form['actions']['submit']['#value'] = $this
->t('Deploy');
}
$form['actions']['submit']['#ajax'] = [
'callback' => [
$this,
'deploy',
],
'event' => 'mousedown',
'prevent' => 'click',
'progress' => [
'type' => 'throbber',
'message' => 'Deploying',
],
];
return $form;
}
public function save(array $form, FormStateInterface $form_state) {
$is_aborted_on_conflict = !$form_state
->hasValue('is_aborted_on_conflict') || $form_state
->getValue('is_aborted_on_conflict') === 'true';
drupal_static('workspace_is_aborted_on_conflict', $is_aborted_on_conflict);
parent::save($form, $form_state);
$input = $form_state
->getUserInput();
$js = isset($input['_drupal_ajax']) ? TRUE : FALSE;
try {
$response = \Drupal::service('workspace.replicator_manager')
->replicate($this->entity
->get('source')->entity, $this->entity
->get('target')->entity, null, $this->entity);
if ($response instanceof ReplicationLogInterface && $response
->get('ok')->value == TRUE) {
$this->entity
->set('replicated', REQUEST_TIME)
->save();
$this
->messenger()
->addMessage($this
->t('Deployment queued, refresh this page and check the status below. It might take a few minutes to complete.'));
if ($form_state
->hasValue('archive') && $form_state
->getValue('archive') == TRUE) {
$this->entity
->setArchiveSource()
->save();
}
if (!$js) {
$form_state
->setRedirect('entity.replication.collection');
}
}
else {
$this
->messenger()
->addError('Deployment error. Check recent log messages for more details.', 'error');
}
} catch (\Exception $e) {
watchdog_exception('Deploy', $e);
$this
->messenger()
->addError($e
->getMessage(), 'error');
}
if (!$js) {
$form_state
->setRedirect('entity.replication.collection');
}
}
public function deploy() {
$response = new AjaxResponse();
$response
->addCommand(new CloseModalDialogCommand());
$response
->addCommand(new RedirectCommand(Url::fromRoute('entity.replication.collection')
->setAbsolute()
->toString()));
return $response;
}
protected function getDefaultSource() {
if (!empty($this->source)) {
return $this->source;
}
if (!empty($this->entity
->get('source')) && $this->entity
->get('source')->entity instanceof WorkspacePointerInterface) {
return $this->source = $this->entity
->get('source')->entity;
}
$workspace = \Drupal::service('workspace.manager')
->getActiveWorkspace();
$workspace_pointers = \Drupal::service('entity_type.manager')
->getStorage('workspace_pointer')
->loadByProperties([
'workspace_pointer' => $workspace
->id(),
]);
return $this->source = reset($workspace_pointers);
}
protected function getDefaultTarget() {
if (!empty($this->target)) {
return $this->target;
}
if (!empty($this->entity
->get('target')) && $this->entity
->get('target')->entity instanceof WorkspacePointerInterface) {
return $this->target = $this->entity
->get('target')->entity;
}
$workspace = \Drupal::service('workspace.manager')
->getActiveWorkspace();
return $this->target = $workspace
->get('upstream')->entity;
}
protected function generateMessageRenderArray($type, $message) {
return [
'#theme' => 'status_messages',
'#message_list' => [
$type => [
Markup::create($message),
],
],
];
}
}