visualn-8.x-1.x-dev/src/Plugin/VisualN/DrawingFetcher/ResourceProviderSwitcherDrawingFetcher.php

src/Plugin/VisualN/DrawingFetcher/ResourceProviderSwitcherDrawingFetcher.php
<?php

namespace Drupal\visualn\Plugin\VisualN\DrawingFetcher;

use Drupal\visualn\Plugin\GenericDrawingFetcherBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\visualn\Manager\DrawerManager;
use Drupal\visualn\Manager\ResourceProviderManager;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Component\Utility\NestedArray;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Render\Element;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\visualn\Helpers\VisualNFormsHelper;
use Drupal\visualn\BuilderService;

use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;

/**
 * Provides a 'Basic (resource provider switcher)' VisualN drawing fetcher.
 *
 * @ingroup fetcher_plugins
 *
 * @VisualNDrawingFetcher(
 *  id = "visualn_resource_provider_switcher",
 *  label = @Translation("Basic (resource provider switcher)"),
 *  context = {
 *    "entity_type" = @ContextDefinition("string", label = @Translation("Entity type"), required = FALSE),
 *    "bundle" = @ContextDefinition("string", label = @Translation("Bundle"), required = FALSE),
 *    "current_entity" = @ContextDefinition("any", label = @Translation("Current entity"), required = FALSE)
 *  }
 * )
 */
class ResourceProviderSwitcherDrawingFetcher extends GenericDrawingFetcherBase {

  /**
   * The visualn resource format manager service.
   *
   * @var \Drupal\visualn\Manager\ResourceProviderManager
   */
  protected $visualNResourceProviderManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager')->getStorage('visualn_style'),
      $container->get('plugin.manager.visualn.drawer'),
      $container->get('visualn.builder'),
      $container->get('plugin.manager.visualn.resource_provider')
    );
  }

  /**
   * Constructs a VisualNFormatter object.
   *
   * @param array $configuration
   *   The plugin configuration, i.e. an array with configuration values keyed
   *   by configuration option name. The special key 'context' may be used to
   *   initialize the defined contexts by setting it to an array of context
   *   values keyed by context names.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition
   * @param \Drupal\Core\Entity\EntityStorageInterface $visualn_style_storage
   *   The visualn style entity storage service.
   * @param \Drupal\visualn\Manager\DrawerManager $visualn_drawer_manager
   *   The visualn drawer manager service.
   * @param \Drupal\visualn\BuilderService $visualn_builder
   *   The visualn builder service.
   * @param \Drupal\visualn\Manager\ResourceProviderManager $visualn_resource_provider_manager
   *   The visualn resource provider manager service.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $visualn_style_storage, DrawerManager $visualn_drawer_manager, BuilderService $visualn_builder, ResourceProviderManager $visualn_resource_provider_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $visualn_style_storage, $visualn_drawer_manager, $visualn_builder);

    $this->visualNResourceProviderManager = $visualn_resource_provider_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'resource_provider_id' => '',
      'resource_provider_config' => [],
      // these settings are provided by GenericDrawingFetcherBase abstract class
      //'visualn_style_id' => '',
      //'drawer_config' => [],
      //'drawer_fields' => [],
    ] + parent::defaultConfiguration();
  }


  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $definitions = $this->visualNResourceProviderManager->getDefinitions();
    $resource_providers = [];
    foreach ($definitions as $definition) {

      // Exclude providers which have at least one required context since here no context is provided.

      // Resource providers may have required contexts some of which are requried only when showing configuration
      // form and some are requried when creating a resource object or both.
      // This means that fetcher may allow user to select such resource providers even if resource generation
      // level required contexts are not there at configuration form level.
      // @todo: Though fetcher can't guess which contexts will be provided by environment when generating
      //   a resource. This issue should be sorted out.
      //   Maybe add a method that would provide the environment with info about optional and required contexts.
      if (!empty($definition['context'])) {
        foreach ($definition['context'] as $name => $context_definition) {
          // @todo: Here we check only contexts required for the form (e.g. we don't check "current_entity" context)
          //    though it may be required for getResourceProviderPlugin() method to work. We suppose that
          //    only "entity_type" and "bundle" are enough here (which generally may be wrong).
          //    Also the "current_entity" context seems to not being checked anywhere and is supposed to work
          //    by convention.
          if (!in_array($name, array('entity_type', 'bundle'))) {
            if ($context_definition->isRequired() && $name != 'current_entity') {
              continue 2;
            }
            continue;
          }
          elseif ($context_definition->isRequired() && !$this->getContextValue($name)) {
            continue 2;
          }
        }
      }

      // Use only providers that have matching contexts or the contexts that are expected
      // to be there when generating a resource.
      // See the notice in @todo: above.
      $resource_providers[$definition['id']] = $definition['label'];
    }

    $ajax_wrapper_id = implode('-', array_merge($form['#array_parents'], ['resource_provider_id'])) .'-ajax-wrapper';

    $form['resource_provider_id'] = [
      '#type' => 'select',
      '#title' => t('Resource provider'),
      '#description' => t('Providers prepare a resource object based on files, urls, data generators etc.'),
      '#default_value' => $this->configuration['resource_provider_id'],
      '#options' => $resource_providers,
      '#required' => TRUE,
      '#empty_value' => '',
      '#empty_option' => t('- Select resource provider -'),
      '#ajax' => [
        'callback' => [get_called_class(), 'ajaxCallbackResourceProvider'],
        'wrapper' => $ajax_wrapper_id,
      ],
    ];
    $form['provider_container'] = [
      '#prefix' => '<div id="' . $ajax_wrapper_id . '">',
      '#suffix' => '</div>',
      '#type' => 'container',
      //'#process' => [[get_called_class(), 'processProviderContainerSubform']],
      '#process' => [[$this, 'processProviderContainerSubform']],
    ];
    $form['provider_container']['#stored_configuration'] = $this->configuration;

    // @todo: no need to set this contexts for resource provider plugins that don't have
    //    them in their annotation (plugin definition), e.g. random data generator plugins.
    // @todo: a similar note should be added to settings context for
    //    generic fetcher plugins (e.g. resource generic fetcher which doesn't need any context to work).
    $form['provider_container']['#entity_type'] = $this->getContextValue('entity_type');
    // @todo: use #entity_bundle key for consistency
    $form['provider_container']['#bundle'] = $this->getContextValue('bundle');

    // Attach visualn style select box for the fetcher
    $form += parent::buildConfigurationForm($form, $form_state);

    return $form;
  }

  /**
   * Return resource provider configuration form via ajax request at style change.
   * Should have a different name since ajaxCallback can be used by base class.
   */
  public static function ajaxCallbackResourceProvider(array $form, FormStateInterface $form_state, Request $request) {
    $triggering_element = $form_state->getTriggeringElement();
    $visualn_style_id = $form_state->getValue($form_state->getTriggeringElement()['#parents']);
    $triggering_element_parents = array_slice($triggering_element['#array_parents'], 0, -1);
    $element = NestedArray::getValue($form, $triggering_element_parents);

    return $element['provider_container'];
  }

  // @todo: this should be static since may not work on field settings form (see fetcher field widget for example)
  //public static function processDrawerContainerSubform(array $element, FormStateInterface $form_state, $form) {
  public function processProviderContainerSubform(array $element, FormStateInterface $form_state, $form) {
    // @todo: explicitly set #stored_configuration and other keys (#entity_type and #bundle) here
    $element = VisualNFormsHelper::doProcessProviderContainerSubform($element, $form_state, $form);
    return $element;
  }


  /**
   * {@inheritdoc}
   */
  public function fetchDrawing() {
    //dsm($this->configuration);

    $resource_provider_id = $this->configuration['resource_provider_id'];
    $resource_provider_config = $this->configuration['resource_provider_config'];
    $visualn_style_id = $this->configuration['visualn_style_id'];
    //if (empty($visualn_style_id) || empty($resource_provider_id)) {
    if (empty($visualn_style_id)) {
      return parent::fetchDrawing();
    }

    $build = [];


    // @todo:

    if (!empty($resource_provider_id)) {
      $provider_plugin = $this->visualNResourceProviderManager->createInstance($resource_provider_id, $resource_provider_config);

      // @todo: maybe $build['drawing'] should be passed to manager but not the $build itself

      $current_entity = $this->getContextValue('current_entity');

      // @todo: replace "any" context type with an appropriate one
      // Set "current_entity" context
      $context_current_entity = new Context(new ContextDefinition('any', NULL, TRUE), $current_entity);
      $provider_plugin->setContext('current_entity', $context_current_entity);
      // @todo: see the note regarding setting context in VisualNResourceProviderItem class

      $drawer_config = $this->configuration['drawer_config'];
      $drawer_fields = $this->configuration['drawer_fields'];

      $resource = $provider_plugin->getResource();

      // Get drawing window parameters
      $window_parameters = $this->getWindowParameters();

      // Get drawing build
      $build = $this->visualNBuilder->makeBuildByResource($resource, $visualn_style_id, $drawer_config, $drawer_fields, '', $window_parameters);

      $drawing_markup = $build;

      // Every resource type is a Typed Data object so it may have its own fixed set of propertries and
      // has validation callback to check if everything is set as expected.
    }



    return $drawing_markup;
  }

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

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

// @todo: add comments everywhere (in particlar to #process callback method code)

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

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