cloud_orchestrator-3.0.0-alpha2/src/Installer/Form/ModuleConfigureForm.php

src/Installer/Form/ModuleConfigureForm.php
<?php

namespace Drupal\cloud_orchestrator\Installer\Form;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleInstallerInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Locale\CountryManager;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Routing\RouteBuilderInterface;
use Drupal\Core\Url;
use Drupal\cloud\Service\CloudServiceInterface;
use Drupal\cloud\Traits\CloudFormTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Additional Cloud Orchestrator related configurations.
 */
class ModuleConfigureForm extends ConfigFormBase {

  use CloudFormTrait;

  /**
   * Drupal\Core\Messenger\MessengerInterface definition.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * Drupal\Core\Config\ConfigFactoryInterface definition.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * Drupal module installer.
   *
   * @var \Drupal\Core\Extension\ModuleInstallerInterface
   */
  protected $moduleInstaller;

  /**
   * Route builder.
   *
   * @var \Drupal\Core\Routing\RouteBuilderInterface
   */
  protected $routeBuilder;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The cloud service.
   *
   * @var \Drupal\cloud\Service\CloudServiceInterface
   */
  protected $cloud;

  /**
   * Module configuration form constructor.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   Config factory.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messanger service.
   * @param \Drupal\Core\Extension\ModuleInstallerInterface $module_installer
   *   The module installer service.
   * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder
   *   The route builder service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   Entity type manager.
   * @param \Drupal\cloud\Service\CloudServiceInterface $cloud
   *   The cloud service.
   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager
   *   The typed config manager.
   */
  public function __construct(
    ConfigFactoryInterface $config_factory,
    MessengerInterface $messenger,
    ModuleInstallerInterface $module_installer,
    RouteBuilderInterface $route_builder,
    EntityTypeManagerInterface $entity_type_manager,
    CloudServiceInterface $cloud,
    TypedConfigManagerInterface $typed_config_manager,
  ) {
    parent::__construct($config_factory, $typed_config_manager);
    $this->messenger = $messenger;
    $this->moduleInstaller = $module_installer;
    $this->routeBuilder = $route_builder;
    $this->entityTypeManager = $entity_type_manager;
    $this->cloud = $cloud;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('config.factory'),
      $container->get('messenger'),
      $container->get('module_installer'),
      $container->get('router.builder'),
      $container->get('entity_type.manager'),
      $container->get('cloud'),
      $container->get('config.typed')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'cloud_orchestrator_module_configure_form';
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames(): array {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $form = parent::buildForm($form, $form_state);
    $form['#title'] = 'Additional configurations';

    // Mock checkboxes showing required providers.
    $form['required_providers'] = [
      '#type' => 'checkboxes',
      '#title' => $this->t('Enabled Cloud Service Providers'),
      '#options' => [
        'aws_cloud' => $this->t('AWS'),
        'k8s' => $this->t('K8s'),
        'openstack' => $this->t('OpenStack'),
        'vmware' => $this->t('VMware'),
        'terraform' => $this->t('Terraform'),
      ],
      '#default_value' => [
        'aws_cloud',
        'k8s',
        'openstack',
        'vmware',
        'terraform',
      ],
      '#description' => $this->t('These cloud service providers are enabled by default'),
      '#disabled' => TRUE,
    ];

    $form['install_ldap'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Install LDAP modules'),
      '#description' => $this->t('Install LDAP modules to authenticate with Active Directory.  LDAP can also be installed at a later time.'),
    ];

    $form['install_spa'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Use React single page application (SPA)'),
      '#description' => $this->t('The React SPA is a javascript UI that interacts with Cloud Orchestrator.'),
      '#default_value' => TRUE,
    ];

    $form['spa'] = [
      '#type' => 'fieldset',
      '#title' => 'SPA settings',
      '#states' => [
        'visible' => [
          ':input[id=edit-install-spa]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    $form['spa']['cloud_spa_key_directory'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Directory for keys'),
      '#description' => $this->t('This is the directory where the public and private keys will be stored. This <strong>SHOULD</strong> be located outside of your webroot to avoid making them public unintentionally.  The directory should be writeable by the webserver.'),
    ];

    global $base_url;
    $form['spa']['cloud_spa_callback_url'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Redirect URI'),
      '#default_value' => $base_url . '/' . Url::fromRoute('cloud_dashboard.endpoint1', [
        'parameter' => 'callback',
      ], [
        'absolute' => TRUE,
      ])->getInternalPath(),
      '#description' => $this->t('The URI the SPA client will redirect to when needed.'),
    ];

    $form['location_map'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Location map'),
      '#open' => TRUE,
    ];

    $form['location_map']['explanation'] = [
      '#type' => 'markup',
      '#markup' => $this->t("Configure the homepage map's default location and zoom level."),
    ];

    $form['location_map']['country'] = [
      '#type' => 'select',
      '#title' => $this->t('Country'),
      // Add a blank option in case users do not want to select a country.
      '#options' => array_merge([
        '' => $this->t('-- Select a country --'),
      ], CountryManager::getStandardList()),
    ];

    $form['location_map']['city'] = [
      '#type' => 'textfield',
      '#title' => $this->t('City'),
    ];

    $form['location_map']['zoom_level'] = [
      '#type' => 'select',
      '#title' => $this->t('Zoom level'),
      '#options' => [
        '1' => $this->t('1'),
        '2' => $this->t('2'),
        '3' => $this->t('3'),
        '4' => $this->t('4'),
        '5' => $this->t('5'),
        '6' => $this->t('6'),
        '7' => $this->t('7'),
        '8' => $this->t('8'),
        '9' => $this->t('9'),
      ],
      '#default_value' => '5',
    ];

    $form['actions']['submit']['#value'] = $this->t('Save and continue');

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state): void {
    // Clear errors before validating again.  For some reason, errors are not
    // cleared out if they have been corrected.
    $this->messenger->deleteAll();

    if ((bool) $form_state->getValue('install_spa') === FALSE) {
      return;
    }

    // Check if the callback URL exists.
    if (empty($form_state->getValue('cloud_spa_callback_url'))) {
      $form_state->setError($form['spa']['cloud_spa_callback_url'], $this->t('Callback url is empty.'));
    }

    // Validate the key directory by using `isDirectory()`.
    if (is_dir($form_state->getValue('cloud_spa_key_directory')) === FALSE) {
      $form_state->setError($form['spa']['cloud_spa_key_directory'], $this->t('Private key directory is not valid. The directory should be the absolute path to a directory outside the webserver document root.'));
      return;
    }

    // Check if the directory is writeable.
    if (is_writable($form_state->getValue('cloud_spa_key_directory')) === FALSE) {
      $form_state->setError($form['spa']['cloud_spa_key_directory'], $this->t('Private key directory is not writeable. The directory should be writeable by the webserver.'));
    }

    // Validate location map input.
    $country = $form_state->getValue('country');
    $city = $form_state->getValue('city');
    if (!empty($country) && empty($city)) {
      $form_state->setError($form['location_map']['city'], $this->t('Please specify a city name.'));
    }

  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $modules = [];

    // Install any additional providers.
    if ((bool) $form_state->getValue('install_ldap') === TRUE) {
      // Add LDAP modules to install.
      $modules = [
        'ldap_user',
        'ldap_servers',
        'ldap_authorization',
        'ldap_query',
        'ldap_authorization',
        'ldap_authentication',
        'authorization',
        'externalauth',
      ];
    }

    if (!empty($modules)) {
      try {
        $this->moduleInstaller->install($modules);
      }
      catch (\Exception $e) {
        $this->messenger->addError($e->getMessage());
      }
    }

    // Set spreadsheet feature to FALSE.
    $this->configFactory
      ->getEditable('aws_cloud.settings')
      ->set('aws_cloud_instance_type_prices_spreadsheet', FALSE)
      ->save();

    $install_spa = (bool) $form_state->getValue('install_spa');

    // The $install_spa === TRUE sets up the proper public and private keys
    // saves it to the simple_oauth.settings configuration object.  Then it
    // creates a oAuth consumer and sets it as default.
    if ($install_spa === TRUE) {
      // Enable the spa.
      $this->enableSpaApp(
        $form_state->getValue('cloud_spa_key_directory'),
        $form_state->getValue('cloud_spa_callback_url')
      );
    }
    // Set up the location map.
    $this->setupLocationMap($form_state);

    // We install some menu links, so we have to rebuild the router,
    // to ensure the menu links are valid.
    $this->routeBuilder->rebuildIfNeeded();
    drupal_flush_all_caches();
  }

  /**
   * Helper method to setup location map defaults.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state object.
   */
  private function setupLocationMap(FormStateInterface $form_state): void {
    // Skip if geocoder is not available.
    if ($this->cloud->isGeocoderAvailable() === FALSE) {
      return;
    }
    $country = $form_state->getValue('country');
    $city = $form_state->getValue('city');
    $zoom_level = $form_state->getValue('zoom_level');
    if (empty($country) || empty($city)) {
      return;
    }
    $provider_id = $this->configFactory
      ->get('cloud.settings')
      ->get('cloud_location_geocoder_plugin');

    if (empty($provider_id)) {
      return;
    }

    try {
      $provider = $this->entityTypeManager->getStorage('geocoder_provider')
        ->load($provider_id);
    }
    catch (\Exception $e) {
      $this->messenger->addError($e->getMessage());
      return;
    }

    $city = $form_state->getValue('city');
    $country = $form_state->getValue('country');
    $address = "$city $country";

    // Call geocoder service without dependency injection as an error occurs
    // when geocoder module does not exist.
    // @codingStandardsIgnoreStart
    $locations = \Drupal::service('geocoder')->geocode($address, [$provider]); // @phpstan-ignore-line
    // @codingStandardsIgnoreEnd

    if (empty($locations)) {
      return;
    }
    $latitude = $locations->first()->getCoordinates()->getLatitude();
    $longitude = $locations->first()->getCoordinates()->getLongitude();
    $config = $this->configFactory()->getEditable('cloud_dashboard.settings');
    $config->set('cloud_dashboard_location_map_country', $country);
    $config->set('cloud_dashboard_location_map_city', $city);
    $config->set('cloud_dashboard_location_map_latitude', $latitude);
    $config->set('cloud_dashboard_location_map_longitude', $longitude);
    $config->set('cloud_dashboard_location_map_zoom_level', $zoom_level);
    $config->save();
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc