View source
<?php
namespace Drupal\apigee_edge\Entity\Form;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\apigee_edge\Entity\ApiProductInterface;
use Drupal\apigee_edge\Entity\Controller\ApiProductControllerInterface;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Url;
use Apigee\Edge\Exception\ApiException;
use Drupal\apigee_edge\Entity\AppInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Link;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Utility\Error;
abstract class AppCreateForm extends AppForm {
protected $apiProductController;
public function __construct(EntityTypeManagerInterface $entity_type_manager, ApiProductControllerInterface $api_product_controller) {
parent::__construct($entity_type_manager);
$this->apiProductController = $api_product_controller;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager'), $container
->get('apigee_edge.controller.api_product'));
}
public final function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$this
->alterFormBeforeApiProductElement($form, $form_state);
$form['api_products'] = $this
->apiProductsFormElement($form, $form_state);
$this
->alterFormWithApiProductElement($form, $form_state);
return $form;
}
protected function alterFormBeforeApiProductElement(array &$form, FormStateInterface $form_state) : void {
}
protected function alterFormWithApiProductElement(array &$form, FormStateInterface $form_state) : void {
}
protected final function apiProductsFormElement(array $form, FormStateInterface $form_state) : array {
$app_settings = $this
->config('apigee_edge.common_app_settings');
$user_select = (bool) $app_settings
->get('user_select');
$api_products_options = array_map(function (ApiProductInterface $product) {
return $product
->label();
}, $this
->apiProductList($form, $form_state));
$multiple = $app_settings
->get('multiple_products');
$default_products = $app_settings
->get('default_products') ?: [];
$element = [
'#title' => $this->entityTypeManager
->getDefinition('api_product')
->getPluralLabel(),
'#required' => TRUE,
'#options' => $api_products_options,
'#access' => $user_select,
'#weight' => 100,
'#default_value' => $multiple ? $default_products : (string) reset($default_products),
'#element_validate' => [
'::validateApiProductSelection',
],
];
if ($app_settings
->get('display_as_select')) {
$element['#type'] = 'select';
$element['#multiple'] = $multiple;
$element['#empty_value'] = '';
}
else {
$element['#type'] = $multiple ? 'checkboxes' : 'radios';
if (!$multiple) {
$element['#options'] = [
'' => $this
->t('N/A'),
] + $element['#options'];
}
}
return $element;
}
public final function validateApiProductSelection(array &$element, FormStateInterface $form_state, array &$complete_form) {
if (!$element['#access']) {
$selected_products = array_values(array_filter((array) $form_state
->getValue($element['#parents'])));
$existing_products = $this->apiProductController
->getEntityIds();
$sanitized_product_list = array_intersect($selected_products, $existing_products);
if ($sanitized_product_list != $selected_products) {
$form_state
->setError($complete_form, $this
->t('@app creation is temporarily disabled. Please contact with support.', [
'@app' => $this
->appEntityDefinition()
->getSingularLabel(),
]));
$this
->logger('apigee_edge')
->critical('Invalid configuration detected! "Let user select the product(s)" is disabled but the submitted app creation form did contain at least one invalid API product. App creation process has been aborted. Please verify the configuration.<br>API product ids in input: <pre>@input</pre> API Product ids on Apigee Edge: <pre>@existing</pre>', [
'link' => Link::fromTextAndUrl($this
->t('configuration'), Url::fromRoute('apigee_edge.settings.general_app'))
->toString(),
'@input' => print_r($selected_products, TRUE),
'@existing' => print_r($existing_products, TRUE),
]);
}
}
}
protected function saveAppCredentials(AppInterface $app, FormStateInterface $form_state) : ?bool {
$result = FALSE;
$app_credential_controller = $this
->appCredentialController($app
->getAppOwner(), $app
->getName());
$logger = $this
->logger('apigee_edge');
$credentials = $app
->getCredentials();
$credential = reset($credentials);
$selected_products = array_values(array_filter((array) $form_state
->getValue('api_products')));
try {
if ($this
->appCredentialLifeTime() === 0) {
$app_credential_controller
->addProducts($credential
->id(), $selected_products);
}
else {
$app_credential_controller
->delete($credential
->id());
$app_credential_controller
->generate($selected_products, $app
->getAttributes(), $app
->getCallbackUrl(), [], $this
->appCredentialLifeTime() * 86400000);
}
$result = TRUE;
} catch (ApiException $exception) {
$context = [
'%app_name' => $app
->label(),
'%owner' => $app
->getAppOwner(),
'link' => $app
->toLink()
->toString(),
];
$context += Error::decodeException($exception);
$logger
->error('Unable to set up app credentials on a created app. App name: %app_name. Owner: %owner. @message %function (line %line of %file). <pre>@backtrace_string</pre>', $context);
try {
$app
->delete();
} catch (EntityStorageException $exception) {
$context = Error::decodeException($exception) + $context;
$logger
->critical('Unable automatically remove %app_name app owned by %owner after app credential set up has failed meanwhile app creation. @message %function (line %line of %file). <pre>@backtrace_string</pre>', $context);
$form_state
->setRedirectUrl($app
->toUrl('collection'));
}
}
return $result;
}
protected function saveButtonLabel() : TranslatableMarkup {
return $this
->t('Add @app', [
'@app' => mb_strtolower($this
->appEntityDefinition()
->getSingularLabel()),
]);
}
}