cc-1.0.x-dev/modules/cc_cex/src/Form/ExchangeApiKeysForm.php
modules/cc_cex/src/Form/ExchangeApiKeysForm.php
<?php
namespace Drupal\cc_cex\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\key\KeyRepositoryInterface;
/**
* Configure exchange API keys.
*/
class ExchangeApiKeysForm extends ConfigFormBase {
/**
* The key repository.
*
* @var \Drupal\key\KeyRepositoryInterface
*/
protected $keyRepository;
/**
* Constructs a new ExchangeApiKeysForm object.
*/
public function __construct(
KeyRepositoryInterface $key_repository
) {
$this->keyRepository = $key_repository;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('key.repository')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'cc_exchange_api_keys_form';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return ['cc.settings'];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('cc.settings');
$enabled_exchanges = $config->get('enabled_exchanges');
$exchange_keys = $config->get('exchange_keys') ?: [];
// Get enabled exchanges list
if (!empty($enabled_exchanges)) {
$exchanges = array_map('trim', explode(',', $enabled_exchanges));
$exchanges = array_filter($exchanges);
}
if (empty($exchanges)) {
$form['no_exchanges'] = [
'#type' => 'markup',
'#markup' => $this->t('No exchanges are enabled. Please <a href="@settings_url">enable some exchanges</a> first.', [
'@settings_url' => Url::fromRoute('cc.exchange_settings')->toString(),
]),
];
return $form;
}
$form['help'] = [
'#type' => 'markup',
'#markup' => '<p>' . $this->t('Configure API keys for each exchange. You must first create two separate keys in the <a href="@keys_url">Key module</a>: one for the API Key and one for the API Secret. Make sure to give your keys the correct permissions on the exchange (e.g., Read-only for viewing balances).', [
'@keys_url' => Url::fromRoute('entity.key.collection')->toString(),
]) . '</p>',
];
$form['exchange_keys'] = [
'#type' => 'container',
'#tree' => TRUE,
];
foreach ($exchanges as $exchange_id) {
if (empty($exchange_id)) continue;
$form['exchange_keys'][$exchange_id] = [
'#type' => 'details',
'#title' => $this->t('@exchange API Keys', ['@exchange' => ucfirst($exchange_id)]),
'#open' => TRUE,
];
// Get current key IDs
$key_config = $exchange_keys[$exchange_id] ?? [];
$form['exchange_keys'][$exchange_id]['api_key_id'] = [
'#type' => 'key_select',
'#title' => $this->t('API Key'),
'#default_value' => $key_config['api_key_id'] ?? '',
'#empty_option' => $this->t('- Select API Key -'),
'#key_filters' => [
'type' => 'authentication',
],
];
$form['exchange_keys'][$exchange_id]['api_secret_id'] = [
'#type' => 'key_select',
'#title' => $this->t('API Secret'),
'#default_value' => $key_config['api_secret_id'] ?? '',
'#empty_option' => $this->t('- Select API Secret -'),
'#key_filters' => [
'type' => 'authentication',
],
];
// Additional parameters container
$form['exchange_keys'][$exchange_id]['additional_params'] = [
'#type' => 'fieldset',
'#title' => $this->t('Additional Parameters'),
'#prefix' => '<div id="additional-params-wrapper-' . $exchange_id . '">',
'#suffix' => '</div>',
];
}
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
$config = $this->config('cc.settings');
$enabled_exchanges = $config->get('enabled_exchanges');
// Get enabled exchanges list
if (!empty($enabled_exchanges)) {
$exchanges = array_map('trim', explode(',', $enabled_exchanges));
$exchanges = array_filter($exchanges);
}
// Check that API keys are properly configured
foreach ($exchanges as $exchange_id) {
if (empty($exchange_id)) continue;
$key_config = $form_state->getValue(['exchange_keys', $exchange_id]);
$has_api_key = !empty($key_config['api_key_id']);
$has_secret = !empty($key_config['api_secret_id']);
// If one is set, both must be set
if ($has_api_key xor $has_secret) {
$form_state->setError(
$form['exchange_keys'][$exchange_id],
$this->t('For @exchange, you must provide both an API Key and an API Secret, or neither.', [
'@exchange' => $exchange_id,
])
);
}
// Validate that the keys exist and are accessible
if ($has_api_key && $has_secret) {
$api_key = $this->keyRepository->getKey($key_config['api_key_id']);
$api_secret = $this->keyRepository->getKey($key_config['api_secret_id']);
if (!$api_key || !$api_key->getKeyValue()) {
$form_state->setError(
$form['exchange_keys'][$exchange_id]['api_key_id'],
$this->t('Could not access the API Key. Please check that the key exists and is properly configured.')
);
}
if (!$api_secret || !$api_secret->getKeyValue()) {
$form_state->setError(
$form['exchange_keys'][$exchange_id]['api_secret_id'],
$this->t('Could not access the API Secret. Please check that the key exists and is properly configured.')
);
}
}
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $this->configFactory->getEditable('cc.settings');
// Save exchange keys
$config->set('exchange_keys', $form_state->getValue('exchange_keys'));
$config->save();
parent::submitForm($form, $form_state);
}
}
