webhooks-8.x-1.x-dev/src/Form/WebhookConfigForm.php

src/Form/WebhookConfigForm.php
<?php

namespace Drupal\webhooks\Form;

use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\webhooks\Entity\WebhookConfig;
use Drupal\webhooks\WebhooksService;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Class Webhook Config Form.
 *
 * @package Drupal\webhooks\Form
 */
final class WebhookConfigForm extends EntityForm {

  /**
   * Webhook service.
   *
   * @var \Drupal\webhooks\WebhooksService
   */
  protected $webhookService;

  /**
   * Module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

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

  /**
   * The entity type bundle info service.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
   */
  protected $entityTypeBundleInfo;

  /**
   * The events.
   *
   * @var array
   */
  protected $events = [];

  /**
   * The entity hooks.
   *
   * @var string[]
   */
  protected $entityHooks = [
    'create',
    'update',
    'delete',
  ];

  /**
   * The system hooks.
   *
   * @var string[]
   */
  protected $systemHooks = [
    'cron',
    'file_download',
    'modules_installed',
    'user_cancel',
    'user_login',
    'user_logout',
    'cache_flush',
  ];

  /**
   * Webhook Config Form constructor.
   *
   * @param \Drupal\webhooks\WebhooksService $webhookService
   *   The webhook service.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
   *   The module handler service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
   *   The entity type manager.
   */
  public function __construct(
    WebhooksService $webhookService,
    ModuleHandlerInterface $moduleHandler,
    EntityTypeManagerInterface $entityTypeManager,
    EntityTypeBundleInfoInterface $entityTypeBundleInfo,
  ) {
    $this->webhookService = $webhookService;
    $this->moduleHandler = $moduleHandler;
    $this->entityTypeManager = $entityTypeManager;
    $this->entityTypeBundleInfo = $entityTypeBundleInfo;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new self(
      $container->get('webhooks.service'),
      $container->get('module_handler'),
      $container->get('entity_type.manager'),
      $container->get('entity_type.bundle.info')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);

    /** @var \Drupal\webhooks\Entity\WebhookConfig $webhook_config */
    $webhook_config = $this->entity;
    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Label'),
      '#maxlength' => 255,
      '#default_value' => $webhook_config->label(),
      '#description' => $this->t('Easily recognizable name for your webhook.'),
      '#required' => TRUE,
    ];
    $form['id'] = [
      '#type' => 'machine_name',
      '#default_value' => $webhook_config->id(),
      // Keep in sync with WebhookTypeForm form id.
      '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
      '#machine_name' => [
        'exists' => '\Drupal\webhooks\Entity\WebhookConfig::load',
      ],
      '#disabled' => !$webhook_config->isNew(),
    ];
    $form['type'] = [
      '#type' => 'select',
      '#title' => $this->t('Type'),
      '#options' => [
        'incoming' => $this->t('Incoming'),
        'outgoing' => $this->t('Outgoing'),
      ],
      '#default_value' => $webhook_config->getType() ? $webhook_config->getType() : 'outgoing',
      '#description' => $this->t('The type of webhook. <strong>Incoming webhooks</strong> receive HTTP events. <strong>Outgoing webhooks</strong> post new events to the configured URL.'),
      '#required' => TRUE,
      '#disabled' => !$webhook_config->isNew(),
    ];
    $form['content_type'] = [
      '#type' => 'select',
      '#title' => $this->t("Content Type"),
      '#description' => $this->t("The Content Type of your webhook."),
      '#options' => [
        WebhookConfig::CONTENT_TYPE_JSON => $this->t('application/json'),
        WebhookConfig::CONTENT_TYPE_XML => $this->t('application/xml'),
        WebhookConfig::CONTENT_TYPE_WWW_FORM_URLENCODED => $this->t('application/x-www-form-urlencoded'),
        WebhookConfig::CONTENT_TYPE_YAML => $this->t('application/yaml'),
      ],
      '#default_value' => $webhook_config->getContentType(),
    ];

    $form['secret'] = [
      '#type' => 'textfield',
      '#attributes' => [
        'placeholder' => $this->t('Secret'),
      ],
      '#title' => $this->t('Secret'),
      '#maxlength' => 255,
      '#description' => $this->t('For <strong>incoming webhooks</strong> this secret is provided by the remote website. For <strong>outgoing webhooks</strong> this secret should be used for the incoming hook configuration on the remote website.'),
      '#default_value' => $webhook_config->getSecret(),
    ];
    $form['token'] = [
      '#type' => 'textfield',
      '#attributes' => [
        'placeholder' => $this->t('Token'),
      ],
      '#title' => $this->t('Token'),
      '#maxlength' => 255,
      '#description' => $this->t('For <strong>incoming webhooks</strong> this secret is provided by the remote website. For <strong>outgoing webhooks</strong> this secret should be used for the incoming hook configuration on the remote website.'),
      '#default_value' => $webhook_config->getToken(),
    ];
    $form['incoming'] = [
      '#title' => $this->t('Incoming Webhook Settings'),
      '#type' => 'details',
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
      '#states' => [
        'expanded' => [
          ':input[name="type"]' => ['value' => 'incoming'],
        ],
        'enabled' => [
          ':input[name="type"]' => ['value' => 'incoming'],
        ],
        'required' => [
          ':input[name="type"]' => ['value' => 'incoming'],
        ],
        'collapsed' => [
          ':input[name="type"]' => ['value' => 'outgoing'],
        ],
        'disabled' => [
          ':input[name="type"]' => ['value' => 'outgoing'],
        ],
        'optional' => [
          ':input[name="type"]' => ['value' => 'outgoing'],
        ],
      ],
    ];
    $form['incoming']['non_blocking'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Non-blocking'),
      '#default_value' => $webhook_config->isNonBlocking(),
      '#description' => $this->t('Non-blocking <strong>incoming webhooks</strong> are stored in a queue for later processing.'),
    ];
    $form['outgoing'] = [
      '#title' => $this->t('Outgoing Webhook Settings'),
      '#type' => 'details',
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
      '#states' => [
        'expanded' => [
          ':input[name="type"]' => ['value' => 'outgoing'],
        ],
        'enabled' => [
          ':input[name="type"]' => ['value' => 'outgoing'],
        ],
        'required' => [
          ':input[name="type"]' => ['value' => 'outgoing'],
        ],
        'collapsed' => [
          ':input[name="type"]' => ['value' => 'incoming'],
        ],
        'disabled' => [
          ':input[name="type"]' => ['value' => 'incoming'],
        ],
        'optional' => [
          ':input[name="type"]' => ['value' => 'incoming'],
        ],
      ],
    ];
    $form['outgoing']['payload_url'] = [
      '#type' => 'url',
      '#title' => $this->t('Payload URL'),
      '#attributes' => [
        'placeholder' => $this->t('http://example.com/post'),
      ],
      '#default_value' => $webhook_config->getPayloadUrl(),
      '#maxlength' => 255,
      '#description' => $this->t('Target URL for your payload. Only used on <strong>outgoing webhooks</strong>.'),
    ];
    $form['outgoing']['events'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Trigger'),
    ];

    foreach ($this->eventOptions() as $event => $options) {
      $default_value = array_intersect(array_keys($options['events']), array_keys($webhook_config->getEvents()));
      $form['outgoing']['events'][$event] = [
        '#title' => $options['label'],
        '#type' => 'details',
        '#open' => !empty($default_value),
        '#tree' => TRUE,
        'events' => [
          '#type' => 'tableselect',
          '#header' => [
            'type' => $this->t('Hook / Event'),
            'event' => $this->t('Machine name'),
          ],
          '#parents' => ['events', $event],
          '#options' => $options['events'],
          '#default_value' => $webhook_config->isNew() ? [] : array_combine($default_value, $default_value),
        ],
      ];
    }

    if ($webhook_config->getType() === 'incoming') {
      unset($form['outgoing']);
    }
    if ($webhook_config->getType() === 'outgoing') {
      unset($form['incoming']);
    }

    $form['status'] = [
      '#type' => 'checkbox',
      '#title' => $this->t("Active"),
      '#description' => $this->t("Shows if the webhook is active or not."),
      '#default_value' => $webhook_config->isNew() ? TRUE : $webhook_config->status(),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    if ($form_state->getValue('type') == 'incoming') {
      // payload_url is required but not used on incoming webhooks.
      // Skipping the value entirely could break data model assumptions.
      $form_state->setValue('payload_url', 'http://example.com/webhook');
    }
    elseif ($form_state->isValueEmpty('payload_url')) {
      $form_state->setErrorByName('payload_url', $this->t('Outgoing webhooks require a Payload URL'));
    }

    if ($form_state->getValue('type') == 'outgoing' && $this->isEmptyList($form_state->getValue('events'))) {
      $form_state->setErrorByName('events');
    }

    parent::validateForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    if ($form_state->getValue('type') === 'outgoing') {
      $events = array_merge(...array_values($form_state->getValue('events')));
      $form_state->setValue('events', $events);
    }
    parent::submitForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    /** @var \Drupal\webhooks\Entity\WebhookConfig $webhook_config */
    $webhook_config = $this->entity;
    // Keep the old secret if no new one has been given.
    if (empty($form_state->getValue('secret'))) {
      $webhook_config->set('secret', $form['secret']['#default_value']);
    }
    $status = $webhook_config->save();

    switch ($status) {
      case SAVED_NEW:
        $this->messenger()->addStatus($this->t(
          'Created the %label Webhook.',
          [
            '%label' => $webhook_config->label(),
          ]
        ));
        break;

      default:
        $this->messenger()->addStatus($this->t(
          'Saved the %label Webhook.',
          [
            '%label' => $webhook_config->label(),
          ]
        ));
    }
    /** @var \Drupal\Core\Url $url */
    $url = $webhook_config->toUrl('collection');
    $form_state->setRedirectUrl($url);
    return $status;
  }

  /**
   * Generate a list of available events.
   *
   * @return array
   *   Array of string identifiers for outgoing event options.
   */
  protected function eventOptions() {
    $options = [];
    $event_class = 'entity';
    foreach ($this->entityTypeManager->getDefinitions() as $entity_type => $definition) {
      if ($definition->entityClassImplements('\Drupal\Core\Entity\ContentEntityInterface')) {
        $event_subclass = implode(':', [$event_class, $entity_type]);
        $options[$event_subclass] = [
          'label' => $this->t('Entity: %entity_label', ['%entity_label' => ucfirst($definition->getLabel())]),
        ];

        foreach ($this->entityHooks as $hook) {
          $event = implode(':', [$event_subclass, $hook]);
          $options[$event_subclass]['events'][$event] = [
            'type' => $this->t('@hook: @entity_label', [
              '@hook' => ucfirst($hook),
              '@entity_label' => $definition->getLabel(),
            ]),
            'event' => $event,
          ];
        }

        foreach ($this->entityTypeBundleInfo->getBundleInfo($entity_type) as $bundle_id => $bundle_definition) {
          foreach ($this->entityHooks as $hook) {
            $event = implode(':', [$event_subclass, $bundle_id, $hook]);
            $options[$event_subclass]['events'][$event] = [
              'type' => $this->t('@hook: @entity_label (@entity_bundle)', [
                '@hook' => ucfirst($hook),
                '@entity_label' => ucfirst($definition->getLabel()),
                '@entity_bundle' => ucfirst($bundle_definition["label"]),
              ]),
              'event' => $event,
            ];
          }
        }
      }
    }

    $event_class = 'system';
    $options[$event_class] = [
      'label' => $this->t('%event_type_label', ['%event_type_label' => ucfirst($event_class)]),
    ];
    foreach ($this->systemHooks as $hook) {
      $event = implode(':', [$event_class, $hook]);
      $options[$event_class]['events'][$event] = [
        'type' => $this->t('%hook_label', ['%hook_label' => ucfirst(str_replace('_', ' ', $hook))]),
        'event' => $event,
      ];
    }

    $this->moduleHandler->alter('webhooks_event_info', $options);
    return $options;
  }

  /**
   * Identifies if an array of form values is empty.
   *
   * FormState::isValueEmpty() does not handle tableselect or #tree submissions.
   *
   * @param array $list
   *   Array of key value pairs. keys are identifiers, values are 0 if empty or
   *   the same value as the key if checked on.
   *
   * @return bool
   *   TRUE if empty, FALSE otherwise.
   */
  protected function isEmptyList(array $list) {
    return count(array_filter(array_merge(...array_values($list)))) == 0;
  }

}

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

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