cloud-8.x-2.0-beta1/cloud.module
cloud.module
<?php
/**
* @file
* Enables users to access the Privately managed clouds.
*
* Provides common functionality for cloud management.
*/
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Locale\CountryManager;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\user\Entity\Role;
use Drupal\views\ViewExecutable;
use Drupal\Component\Serialization\Yaml;
/**
* Implements hook_help().
*/
function cloud_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.cloud':
$output = '<p>' . t('The cloud module creates a user interface for users to manage clouds. Users can Create Instances, Describe Instances etc.') . '</p>';
return $output;
case 'help.page.cloud_server_template':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Cloud server template') . '</p>';
$output .= '<p>' . t('The cloud_server_template module creates a user interface for users to manage clouds. Users can create cloud server templates.') . '</p>';
return $output;
default:
return '';
}
}
/**
* Implements hook_theme().
*/
function cloud_theme() {
$theme = [];
$theme['cloud_config'] = [
'render element' => 'elements',
'file' => 'cloud_config.page.inc',
'template' => 'cloud_config',
];
$theme['cloud_config_content_add_list'] = [
'render element' => 'content',
'variables' => ['content' => NULL],
'file' => 'cloud_config.page.inc',
];
$theme['cloud_server_template'] = [
'render element' => 'elements',
'file' => 'cloud_server_template.page.inc',
'template' => 'cloud_server_template',
];
$theme['cloud_server_template_content_add_list'] = [
'render element' => 'content',
'variables' => ['content' => NULL],
'file' => 'cloud_server_template.page.inc',
];
return $theme;
}
/**
* Implements hook_theme_suggestions_HOOK().
*/
function cloud_theme_suggestions_cloud_config(array $variables) {
$suggestions = [];
$entity = $variables['elements']['#cloud_config'];
$sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
$suggestions[] = 'cloud_config__' . $sanitized_view_mode;
$suggestions[] = 'cloud_config__' . $entity->bundle();
$suggestions[] = 'cloud_config__' . $entity->bundle() . '__' . $sanitized_view_mode;
$suggestions[] = 'cloud_config__' . $entity->id();
$suggestions[] = 'cloud_config__' . $entity->id() . '__' . $sanitized_view_mode;
return $suggestions;
}
/**
* Implements hook_theme_suggestions_HOOK().
*/
function cloud_theme_suggestions_cloud_server_template(array $variables) {
$suggestions = [];
$entity = $variables['elements']['#cloud_server_template'];
$sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
$suggestions[] = 'cloud_server_template__' . $sanitized_view_mode;
$suggestions[] = 'cloud_server_template__' . $entity->bundle();
$suggestions[] = 'cloud_server_template__' . $entity->bundle() . '__' . $sanitized_view_mode;
$suggestions[] = 'cloud_server_template__' . $entity->id();
$suggestions[] = 'cloud_server_template__' . $entity->id() . '__' . $sanitized_view_mode;
return $suggestions;
}
/**
* Implements hook_views_pre_render().
*
* This is a workaround to implement row level access control,
* until this issue is resolved:
* https://www.drupal.org/project/entity/issues/2909970
* Loop through the results,
* and call hasPermissions() with the entity's cloud_context.
* Unset the entity if the user does not have permissions.
*/
function cloud_views_pre_render(ViewExecutable $view) {
$account = \Drupal::currentUser();
if ($view->id() == 'cloud_config' || $view->id() == 'cloud_server_template') {
foreach ($view->result as $key => $result) {
/* @var \Drupal\cloud\Entity\CloudConfigInterface $cloud */
$cloud = $result->_entity;
if (!$account->hasPermission('view ' . $cloud->getCloudContext())
&& !$account->hasPermission('view all cloud service providers')) {
unset($view->result[$key]);
}
}
}
}
/**
* Helper function to install or update configuration for a set of yml files.
*
* @param array $files
* An array of yml file names.
* @param string $module_name
* Module where the files are found.
*/
function cloud_update_yml_definitions(array $files, $module_name = 'cloud') {
$config_manager = \Drupal::service('config.manager');
$config_path = realpath(drupal_get_path('module', $module_name)) . '/config/install';
foreach ($files as $file) {
$filename = $config_path . '/' . $file;
$file = file_get_contents($filename);
if (!$file) {
continue;
}
$value = Yaml::decode($file);
$type = $config_manager->getEntityTypeIdByName(basename($filename));
$entity_manager = $config_manager->getEntityTypeManager();
$definition = $entity_manager->getDefinition($type);
$id_key = $definition->getKey('id');
$id = $value[$id_key];
$entity_storage = $entity_manager->getStorage($type);
$entity = $entity_storage->load($id);
if ($entity) {
$entity = $entity_storage->updateFromStorageRecord($entity, $value);
$entity->save();
}
else {
$entity = $entity_storage->createFromStorageRecord($value);
$entity->save();
}
}
}
/**
* Delete views by ids.
*
* @param array $ids
* An array of view ids.
*/
function cloud_delete_views(array $ids) {
$config_manager = \Drupal::service('config.manager');
foreach ($ids as $id) {
$entity_manager = $config_manager->getEntityTypeManager();
$entity_storage = $entity_manager->getStorage('view');
$view_storage = $entity_storage->load($id);
if ($view_storage) {
$view_storage->delete();
}
}
}
/**
* Implements hook_form_alter().
*
* Hook for form views_form_cloud_config_*.
*/
function cloud_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if (strpos($form_id, 'views_form_cloud_config_') === 0) {
$form['#submit'][] = 'cloud_config_bulk_form_submit';
}
}
/**
* Submit function for form views_form_cloud_config_list.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
function cloud_config_bulk_form_submit(array $form, FormStateInterface $form_state) {
$form_state->setRedirect(
'entity.cloud_config.delete_multiple_form', [
'cloud_config' => 'cloud_config',
]
);
}
/**
* Submit function for form views_form_cloud_*.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
function cloud_views_bulk_form_submit(array $form, FormStateInterface $form_state) {
$request = \Drupal::service('request_stack')->getCurrentRequest();
$action = $form_state->getValue('action');
// Get entity_type and operation name.
// $action - Format: '{entity_type}_{operation}_action'.
preg_match('/^(.+)_(.+)_action/', $action, $matches);
$entity_type = $matches[1];
$operation = $matches[2];
// Change the confirm form.
// Format: 'entity.{entity_type}.{operation}_multiple_form'.
$form_state->setRedirect(
"entity.${entity_type}.${operation}_multiple_form", [
'cloud_context' => $request->get('cloud_context'),
]
);
}
/**
* Function to reorder form values.
*
* @param array $form
* Form elements.
* @param array $fieldset_defs
* Field set definitions.
*/
function cloud_form_reorder(array &$form, array $fieldset_defs) {
$weight = 0;
foreach ($fieldset_defs as $fieldset_def) {
$fieldset_name = $fieldset_def['name'];
$form[$fieldset_name] = [
'#type' => 'details',
'#title' => $fieldset_def['title'],
'#weight' => $weight++,
'#open' => $fieldset_def['open'],
];
foreach ($fieldset_def['fields'] as $field_name) {
if (!isset($form[$field_name])) {
continue;
}
$form[$fieldset_name][$field_name] = $form[$field_name];
$form[$fieldset_name][$field_name]['#weight'] = $weight++;
unset($form[$field_name]);
}
// Support second level fieldset.
if (isset($fieldset_def['subfieldsets'])) {
foreach ($fieldset_def['subfieldsets'] as $subfieldset_def) {
$subfieldset_name = $subfieldset_def['name'];
$form[$fieldset_name][$subfieldset_name] = [
'#type' => 'details',
'#title' => $subfieldset_def['title'],
'#weight' => $weight++,
'#open' => $subfieldset_def['open'],
];
foreach ($subfieldset_def['fields'] as $subfield) {
if (!isset($form[$subfield])) {
continue;
}
$form[$fieldset_name][$subfieldset_name][$subfield] = $form[$subfield];
$form[$fieldset_name][$subfieldset_name][$subfield]['#weight'] = $weight++;
unset($form[$subfield]);
}
// Third level field set.
if (isset($subfieldset_def['subfieldsets'])) {
foreach ($subfieldset_def['subfieldsets'] as $third_fieldset_def) {
$third_fieldset_name = $third_fieldset_def['name'];
$form[$fieldset_name][$subfieldset_name][$third_fieldset_name] = [
'#type' => 'details',
'#title' => $third_fieldset_def['title'],
'#weight' => $weight++,
'#open' => $third_fieldset_def['open'],
];
foreach ($third_fieldset_def['fields'] as $third_field) {
if (!isset($form[$third_field])) {
continue;
}
$form[$fieldset_name][$subfieldset_name][$third_fieldset_name][$third_field] = $form[$third_field];
$form[$fieldset_name][$subfieldset_name][$third_fieldset_name][$third_field]['#weight'] = $weight++;
unset($form[$third_field]);
}
}
}
}
}
}
}
/**
* Implements hook_entity_view_alter().
*/
function cloud_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
$build['#attached']['library'][] = 'cloud/cloud_view_builder';
}
/**
* Helper function to rename permissions.
*
* @param array $permission_map
* A array map of ['current_permission_name' => 'new_permission_name'].
*/
function cloud_update_permissions(array $permission_map) {
$roles = Role::loadMultiple();
foreach ($roles as $role) {
$permissions = $role->getPermissions();
foreach ($permissions as $permission) {
if (array_key_exists($permission, $permission_map)) {
$role->revokePermission($permission);
$role->grantPermission($permission_map[$permission]);
$role->save();
}
}
}
}
/**
* Set dynamic allowed values for the location country field.
*
* @param \Drupal\field\Entity\FieldStorageConfig $definition
* The field definition.
* @param \Drupal\Core\Entity\ContentEntityInterface|null $entity
* The entity being created if applicable.
* @param bool $cacheable
* Boolean indicating if the results are cacheable.
*
* @return array
* An array of possible key and value options.
*
* @see options_allowed_values()
*/
function cloud_location_country_allowed_values_function(FieldStorageConfig $definition = NULL, ContentEntityInterface $entity = NULL, $cacheable = FALSE) {
return CountryManager::getStandardList();
}
/**
* Implements hook_preprocess_views_view().
*/
function cloud_preprocess_views_view(&$variables) {
$view = $variables['view'];
if ($view->id() == 'cloud_config') {
$variables['#attached']['library'][] = "cloud/cloud_config_location";
$block_manager = \Drupal::service('plugin.manager.block');
$config = ['not_display_cloud_config_page' => TRUE];
$plugin_block = $block_manager->createInstance('cloud_config_location', $config);
$render = $plugin_block->build();
$variables['header']['cloud_config_location'] = $render;
}
}
/**
* Implements hook_field_widget_form_alter().
*/
function cloud_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
$field_definition = $context['items']->getFieldDefinition();
$settings = $field_definition->getSettings();
if ($field_definition->getName() === 'field_location_latitude' || $field_definition->getName() === 'field_location_longitude') {
// @TODO Prevents validation of decimal numbers.
// @see https://www.drupal.org/node/2230909
$element['value']['#step'] = 'any';
$element['value']['#scale'] = $settings['scale'];
}
}
/**
* Implements hook_preprocess_input__number().
*/
function cloud_preprocess_input__number(&$variables) {
$element = &$variables['element'];
if (strpos($element['#name'], 'field_location_latitude') !== FALSE || strpos($element['#name'], 'field_location_longitude') !== FALSE) {
// @TODO Enable the validation only on the browser for step settings.
// @see https://www.drupal.org/node/2230909
$scale = $element['#scale'];
$variables['attributes']['step'] = pow(0.1, $scale);
}
}
