openlayers-8.x-4.x-dev/src/Plugin/Control/LayerSwitcher/LayerSwitcher.php
src/Plugin/Control/LayerSwitcher/LayerSwitcher.php
<?php
namespace Drupal\openlayers\Plugin\Control\LayerSwitcher;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Html;
use Drupal\openlayers\Types\Control;
use Drupal\openlayers\Types\ObjectInterface;
use Drupal\openlayers\Openlayers;
/**
* Defines the Layer Switcher control for an Openlayers map.
*
* @OpenlayersPlugin(
* id = "ol_control_layerswitcher",
* label = @Translation("Layer switcher"),
* description = @Translation("Define a layer switcher control."),
* service = "openlayers.Control:LayerSwitcher",
* library = "openlayers-plugin-control-layerswitcher",
* is_configurable = "true",
* type = "control"
* )
*/
class LayerSwitcher extends Control {
/**
* {@inheritdoc}
*/
public function getSummary() {
$summary = [
'#theme' => 'openlayers_control_summary',
'#data' => $this->configuration,
];
$summary += parent::getSummary();
return $summary;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'label' => 'Label XX',
'layers' => [],
'className' => 'ol-layerswitcher-XX',
'multiselect' => true,
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
foreach($form['options'] as $key => $item) {
$this->configuration[$key] = $form['options'][$key];
}
// Get, decorate and order all layers.
$all_layers = Openlayers::loadAllAsOptions('Layer');
foreach ($all_layers as $machine_name => $name) {
$selected = TRUE;
if (($layer = Openlayers::load('Layer', $machine_name)) == TRUE)
$selected = $layer->getOption('visible', 1) != 0;
$all_layers[$machine_name] = array('name' => $name,
// 'weight' => PHP_INT_MAX, // TODO
'weight' => 0,
'label' => $name,
'selected' => $selected,
'enabled' => FALSE,
);
}
$all_layers = array_merge($all_layers, $this->getOptionLayers());
uasort($all_layers, function($a, $b) {
if ($a['enabled'] != $b['enabled'])
return $a['enabled']? -1: 1;
if ($a['weight'] != $b['weight'])
return $a['weight'] - $b['weight'];
if ($a['name'] != $b['name'])
return strcmp($a['name'], $b['name']);
return strcmp($a['name'], $b['name']);
});
// Build layers table.
$rows = array();
$weight = 0;
// Build form.
$form['options']['label'] = array(
'#type' => 'textfield',
'#title' => t('Title of the control'),
'#default_value' => isset($this->configuration['label']) ? $this->configuration['label'] : 'Layers',
);
$form['options']['multiselect'] = array(
'#type' => 'checkbox',
'#title' => t('Allow selecting multiple layers'),
'#default_value' => isset($this->configuration['multiselect']) ? $this->configuration['multiselect'] : false,
);
$form['options']['className'] = [
'#type' => 'textfield',
'#default_value' => isset($this->configuration['className']) ? $this->configuration['className'] : '',
'#title' => t('Class name'),
'#description' => t('CSS class name.'),
'#size' => 50,
'#maxlength' => 50,
'#required' => FALSE,
];
$form['options']['layers'] = array(
'#type' => 'table',
'#header' => array(
'name' => t('Name'),
'enabled' => t('Enabled'),
'label' => t('Label'),
'selected' => t('Selected'),
'weight' => t('Weight'),
),
'#empty' => t('There are no entries available.'),
'#sticky' => TRUE,
// drupal_add_tabledrag('layerswitcher-order', 'order', 'sibling', 'layerswitcher-order-weight'); // TODO - replace drupal_add_tabledrag
// Properties for tabledrag support.
// The value is a list of arrays that are passed to
// drupal_attach_tabledrag(). Table::preRenderTable() prepends the HTML ID
// of the table to each set of options.
// @see drupal_attach_tabledrag()
// TableDrag: Each array value is a list of callback arguments for
// drupal_add_tabledrag(). The #id of the table is automatically
// prepended; if there is none, an HTML ID is auto-generated.
'#tabledrag' => [
[
'action' => 'order',
'relationship' => 'sibling',
'group' => 'table-sort-weight',
],
],
);
// Build the table rows and columns.
foreach ($all_layers as $id => $layer) {
if (isset($this->configuration['layers'][$id])) {
$config = $this->configuration['layers'][$id];
} else {
$config = [];
}
$form['options']['layers'][$id]['#attributes']['class'][] = 'draggable';
// TableDrag: Sort the table row according to its existing/configured
// weight.
$form['options']['layers'][$id]['#weight'] = isset($config['weight']) ? $config['weight'] : $layer['weight'];
// Some table columns containing raw markup.
$form['options']['layers'][$id]['name'] = [
'#markup' => $layer['name'],
];
$form['options']['layers'][$id]['enabled'] = [
'#type' => 'checkbox',
'#default_value' => isset($config['enabled']) ? $config['enabled'] : $layer['enabled'],
];
$form['options']['layers'][$id]['label'] = [
'#type' => 'textfield',
'#required' => TRUE,
'#default_value' => isset($config['label']) ? $config['label'] : $layer['label'],
];
$form['options']['layers'][$id]['selected'] = [
'#type' => 'checkbox',
'#default_value' => isset($config['selected']) ? $config['selected'] : $layer['selected'],
];
// TableDrag: Weight column element.
$form['options']['layers'][$id]['weight'] = [
'#type' => 'weight',
'#title' => $this
->t('Weight for @title', [
'@title' => $layer['name'],
]),
'#title_display' => 'invisible',
'#default_value' => isset($config['weight']) ? $config['weight'] : $layer['weight'],
// Classify the weight element for #tabledrag.
'#attributes' => [
'class' => [
'table-sort-weight',
],
],
];
}
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
foreach($form_state->getValues() as $key => $item) {
$this->configuration[$key] = $form_state->getValue($key);
}
// Process labels i18n updates, order layers and drop unneeded values.
if ($form_state->getValue('options') !== null) {
$all_layers = Openlayers::loadAllAsOptions('Layer');
$options = &$form_state->getValue('options');
if (isset($options['layers'])) {
$layers = &$options['layers'];
uasort($layers, function($a, $b) {
if ($a['enabled'] != $b['enabled'])
return $a['enabled']? -1: 1;
return $a['weight'] - $b['weight'];
});
foreach ($layers as $id => $layer) {
$label = '';
if (!$layer['enabled'])
unset($layers[$id]);
else {
$label = $layer['label'];
if ($label == '')
$label = isset($all_layers[$id])? $all_layers[$id]: $id;
unset($layers[$id]['weight']);
unset($layers[$id]['enabled']);
}
}
}
}
}
/**
* {@inheritdoc}
*/
public function preBuild(array &$build, ObjectInterface $context = NULL) {
$map_id = $context->getId();
$layers = $this->getOptionLayers();
$items = array();
$map_layers = array();
foreach ($context->getObjects('layer') as $map_layer)
$map_layers[$map_layer->getMachineName()] = $map_layer;
$multiselect = $this->getOption('multiselect', FALSE);
$element_type = $multiselect ? 'checkbox' : 'radio';
// Only handle layers available in the map and configured in the control.
// @TODO: use Form API (with form_process_* and stuff)
$selection = FALSE;
foreach ($layers as $id => $layer) {
if (!isset($map_layers[$id]))
unset($layers[$id]);
else if ($layer['selected']) {
if (!$multiselect && $selection)
$layers[$id]['selected'] = FALSE;
$selection = TRUE;
}
}
if (!$multiselect && !$selection) {
foreach ($layers as $id => $layer) {
$layers[$id]['selected'] = TRUE;
break;
}
}
foreach ($layers as $id => $layer) {
$classes = array(Html::getClass($id));
$checked = $layer['selected']? 'checked="checked" ': '';
// $label = openlayers_i18n_string('openlayers:layerswitcher:' . $this->getMachineName() . ':' . $id . ':label', $layer['label'], array('sanitize' => TRUE));
$label = $layer['label']; // TODO temp line
$items[] = array(
// 'data' => '<label><input type="' . $element_type . '" name="layer" ' . $checked . 'value="' . $id . '">' . $label . '</label>',
'#markup' => '<label><input type="' . $element_type . '" name="layer" ' . $checked . 'value="' . $id . '">' . $label . '</label>',
// 'id' => Html::getUniqueId($map_id . '-' . $id),
// 'class' => $classes,
'#attributes' => ['id' => Html::getUniqueId($map_id . '-' . $id), 'class' => $classes],
);
}
$layerswitcher = array(
'#theme' => 'item_list',
'#type' => 'ul',
'#items' => $items,
'#attributes' => array(
'id' => Html::getUniqueId($this->getMachineName() . '-items'),
),
);
$title = $this->getOption('options')['label'];
if ($title != '<none>') {
// $title = openlayers_i18n_string('openlayers:layerswitcher:' . $this->getMachineName() . ':title', $title, array('sanitize' => TRUE)); // TODO
$layerswitcher['#title'] = $title;
}
$this->setOption('element', '<div id="' . Html::getUniqueId($this->getMachineName()) . '" class="' . Html::getClass($this->getMachineName()) . ' layerswitcher">' . \Drupal::service('renderer')->renderPlain($layerswitcher) . '</div>');
// Allow the parent class to perform it's pre-build actions.
parent::preBuild($build, $context);
}
/**
* Get layers from options, converting them from old storage style if
* needed and decorating them with additional properties.
*/
private function getOptionLayers() {
$option_layers = $this->getOptions()['options']['layers'];
$labels = $this->getOption('layer_labels', array());
$layers = array();
$weight = 0;
foreach ($option_layers as $machine_name => $params) {
$name = $machine_name;
$selected = TRUE;
if (($map_layer = Openlayers::load('Layer', $machine_name)) == TRUE) {
$name = $map_layer->getName();
$selected = $map_layer->getOption('visible', 1) != 0;
}
if (!is_array($params)) { /* Old-style options. */
$label = isset($labels[$machine_name])? $labels[$machine_name]: $name;
$params = array('label' => $label, 'selected' => $selected);
}
$params['name'] = $name;
$params['enabled'] = TRUE;
$params['weight'] = $weight++;
$layers[$machine_name] = $params;
}
return $layers;
}
}
