rocketship_core-8.x-2.0-alpha11/src/Plugin/DsField/ConfigurableLink.php

src/Plugin/DsField/ConfigurableLink.php
<?php

namespace Drupal\rocketship_core\Plugin\DsField;

use Drupal\Core\Entity\Element\EntityAutocomplete;
use Drupal\Core\Form\FormStateInterface;
use Drupal\ds\Plugin\DsField\DsFieldBase;
use Drupal\Core\Url;
use Drupal\Core\Link;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Utility\Token;
use Drupal\Core\Path\AliasStorageInterface;

/**
 * Outputs a link that is configurable.
 *
 * @DsField(
 *   id = "configurable_link",
 *   title = @Translation("Configurable link"),
 *   entity_type =  {"node","taxonomy_term"},
 *   provider = "rocketship_core"
 * )
 */
class ConfigurableLink extends DsFieldBase {

  /**
   * The Token service.
   *
   * @var \Drupal\Core\Utility\Token
   */
  protected $token;

  /**
   * Provides a service for CRUD operations on path aliases.
   *
   * @var \Drupal\Core\Path\AliasStorageInterface
   */
  protected $aliasStorage;

  /**
   * Constructs a Display Suite field plugin.
   */
  public function __construct($configuration, $plugin_id, $plugin_definition, Token $token_service, AliasStorageInterface $alias_storage) {
    $this->token = $token_service;
    $this->aliasStorage = $alias_storage;
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {

    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('token'),
      $container->get('path.alias_storage')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'link' => '',
      'link_text' => 'Back to overview',
      'link_class' => '',
      'query_string' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary($settings) {
    $config = $this->getConfiguration();

    $summary = [];
    $summary[] = 'Url: ' . $config['link'];
    $summary[] = 'Link text: ' . $config['link_text'];
    $summary[] = 'Class: ' . $config['link_class'];
    $summary[] = 'Query string: ' . isset($config['query_string']) ? $config['query_string'] : '';

    return $summary;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm($form, FormStateInterface $form_state) {
    $config = $this->getConfiguration();

    $form['link'] = [
      '#type' => 'entity_autocomplete',
      '#target_type' => 'node',
      '#process_default_value' => FALSE,
      '#title' => $this->t('URL'),
      '#default_value' => $config['link'],
      '#description' => $this->t('Start typing the title of a piece of content to select it. You can also enter an internal path such as %add-node or an external URL such as %url. Enter %front to link to the front page. Token input is available, if token replacement will result with empty text link will not be rendered.', [
        '%front' => '<front>',
        '%add-node' => '/node/add',
        '%url' => 'http://example.com',
      ]),
      '#required' => TRUE,
      '#element_validate' => [[get_called_class(), 'validateUriElement']],
    ];
    $form['link_text'] = [
      '#title' => t('Link text'),
      '#description' => t('Text for the link.'),
      '#type' => 'textfield',
      '#default_value' => $config['link_text'],
      '#required' => TRUE,
    ];
    $form['link_class'] = [
      '#title' => t('Link class'),
      '#description' => t('Classes separated with a comma.'),
      '#type' => 'textfield',
      '#default_value' => $config['link_class'],
      '#required' => FALSE,
    ];
    $form['query_string'] = [
      '#title' => 'Query String',
      '#description' => 'Add the query string which should be added to the link, eg: title=My Title&subject=[node:title]. Do NOT include the "?"',
      '#type' => 'textfield',
      '#default_value' => isset($config['query_string']) ? $config['query_string'] : NULL,
      '#required' => FALSE,
    ];

    $form['tokens'] = [
      '#theme' => 'token_tree_link',
      '#token_types' => $this->getEntityTypeId() == 'node' ? ['node'] : ['term'],
      '#show_restricted' => FALSE,
      '#dialog' => TRUE,
    ];

    return $form;
  }

  /**
   * Form element validation handler for the URL element of link widget.
   *
   * @param array $element
   *   Element.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   * @param array $form
   *   Form.
   *
   * @see \Drupal\link\Plugin\Field\FieldWidget\LinkWidget
   */
  public static function validateUriElement(array $element,
                                            FormStateInterface $form_state,
                                            array $form) {
    $uri = static::getUserEnteredStringAsUri($element['#value']);
    $form_state->setValueForElement($element, $uri);

    // If getUserEnteredStringAsUri() mapped the entered value to a 'internal:'
    // URI , ensure the raw value begins with '/', '?' or '#'.
    // @todo '<front>' is valid input for BC reasons, may be removed by
    //   https://www.drupal.org/node/2421941
    if (parse_url($uri, PHP_URL_SCHEME) === 'internal' && !in_array($element['#value'][0],
        [
          '/',
          '?',
          '#',
        ], TRUE) && substr($element['#value'], 0, 7) !== '<front>') {
      $form_state->setError($element, t('Manually entered paths should start with /, ? or #.'));
      return;
    }
  }

  /**
   * Gets the user-entered string as a URI.
   *
   * @param string $string
   *   String.
   *
   * @return string
   *   The URI.
   *
   * @see \Drupal\link\Plugin\Field\FieldWidget\LinkWidget
   */
  protected static function getUserEnteredStringAsUri($string) {
    // By default, assume the entered string is an URI.
    $uri = trim($string);
    // Detect entity autocomplete string, map to 'entity:' URI.
    $entity_id = EntityAutocomplete::extractEntityIdFromAutocompleteInput($string);
    if ($entity_id !== NULL) {
      // @todo Support entity types other than 'node'. Will be fixed in
      //   https://www.drupal.org/node/2423093.
      $uri = 'entity:node/' . $entity_id;
    }
    // Detect a schemeless string, map to 'internal:' URI.
    elseif (!empty($string) && parse_url($string, PHP_URL_SCHEME) === NULL) {
      // @todo '<front>' is valid input for BC reasons, may be removed by
      //   https://www.drupal.org/node/2421941
      // - '<front>' -> '/'
      // - '<front>#foo' -> '/#foo'
      if (strpos($string, '<front>') === 0) {
        $string = '/' . substr($string, strlen('<front>'));
      }
      $uri = 'internal:' . $string;
    }

    return $uri;
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    // Get the config.
    $config = $this->getConfiguration();

    // Tokenize link title.
    $link_text = $this->token->replace($config['link_text'], [$this->getEntityTypeId() => $this->entity()], ['clear' => TRUE]);

    if (!strlen($link_text)) {
      return FALSE;
    }

    // Try to tokenize link URL.
    $link = $this->token->replace($config['link'], [$this->getEntityTypeId() => $this->entity()], ['clear' => TRUE]);

    // Prepare the url.
    $url = Url::fromUri($link);

    // Extra check for cases when configured URL is a path alias,
    // then we need to get source path like /node/{nid} so it will nicely
    // work with different languages.
    $langcode = $this->entity()->language()->getId();
    $source = $this->aliasStorage->lookupPathSource($url->toString(), $langcode);
    if ($source) {
      $url = Url::fromUri($this::getUserEnteredStringAsUri($source));
    }

    // Check if we have classes available.
    if (!empty($config['link_class'])) {
      $url->setOption('attributes', ['class' => explode(',', $config['link_class'])]);
    }

    // Add the query string if available.
    if (!empty($config['query_string'])) {
      // Get it all parsed and translated.
      $query_array = $this->parseString($config['query_string']);
      $url->setOption('query', $query_array);
    }

    return Link::fromTextAndUrl($this->t($link_text), $url)
      ->toRenderable();
  }

  /**
   * Parses query string in CGI-compliant way.
   *
   * Also translates and tokenizes values.
   *
   * @param string $str
   *   String to parse into an array.
   *
   * @return array
   *   Returned array.
   *
   * @see https://php.net/manual/en/function.parse-str.php#76792
   */
  protected function parseString($str) {
    $arr = [];
    $pairs = explode('&', $str);
    foreach ($pairs as $i) {
      list($name, $value) = explode('=', $i, 2);
      // Translate then tokenize value.
      $value = $this->token->replace(t($value), [$this->getEntityTypeId() => $this->entity()], ['clear' => TRUE]);
      if (isset($arr[$name])) {
        if (is_array($arr[$name])) {
          $arr[$name][] = $value;
        }
        else {
          $arr[$name] = [$arr[$name], $value];
        }
      }
      else {
        $arr[$name] = $value;
      }
    }
    return $arr;
  }

}

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

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