murmurations-1.0.0-alpha1/src/Form/FilterForm.php

src/Form/FilterForm.php
<?php

namespace Drupal\murmurations\Form;

use Drupal\murmurations\MurmurationsPluginManager;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\Entity\User;
use Drupal\user\UserData;
use Drupal\Core\Render\Markup;
use Drupal\Core\Routing\CurrentRouteMatch;
use Symfony\Component\HttpFoundation\Request;
use GuzzleHttp\Psr7\Response;

//@todo inject messenger, guzzle,.
abstract class FilterForm extends FormBase {

  /**
   * @var Symfony\Component\HttpFoundation\Request
   */
  protected $request;

  /**
   * @var UserData
   */
  protected $userData;

  /**
   * @var MurmurationsPluginManager
   */
  protected $plugin;

  /**
   * @var CurrentRouteMatch
   */
  protected $route_match;

  /**
   * @var The current user ID
   */
  protected $uid;

  /**
   * @var array
   * The params collected by the form
   */
  protected $params;

  /**
   * @var string
   * The url of the aggregator with a trailing slash.
   */
  protected string $aggregator;

  /**
   * @param UserData $user_data
   * @param Request $request
   * @param CurrentRouteMatch $route_match
   * @param MurmurationsPluginManager $murm_plugin_manager
   */
  public function __construct(UserData $user_data, Request $request, CurrentRouteMatch $route_match, MurmurationsPluginManager $murm_plugin_manager) {
    $this->userData = $user_data;
    $this->request = $request;
    $this->routeMatch = $route_match;
    $plugin_id = $request->attributes->get('_route_object')->getOptions()['plugin'];
    $this->plugin = $murm_plugin_manager->createInstance($plugin_id);
    $this->uid = $this->currentUser()->id();
    $this->aggregator = $this->plugin->getConfiguration()['aggregator_url'];
    if (substr($this->aggregator, -1) <> '/') $this->aggregator .= '/';
    $this->aggregator .= $this->plugin->getPluginDefinition()['schema'];
  }

  /**
   * {@inheritDoc}
   */
  function buildForm(array $form, FormStateInterface $form_state) {
    $this->params = $this->request->query->all();

    $form['basic'] = [
      '#type' => 'container',
      'range' => [
        '#title' => $this->t('Max distance'),
        '#description' => $this->t('from me (0 means any)'),
        '#type' => 'number',
        '#default_value' => $this->userData->get('murmurations', $this->uid, 'range')??5,
        '#field_suffix' => 'km',
        '#access' => (bool)$this->config('murmurations.settings')->get('fallback_point.lat'), // ONly show
        '#weight' => 1,
        '#size' => 6
      ],
      'fragment' => [
        '#title' => $this->t('Keywords'),
        '#description' => $this->t('Separated by commas for OR'),
        '#type' => 'textfield',
        '#default_value' => $this->params['fragment']??'',
        '#weight' => 2,
        '#size' => 10
      ],
      '#weight' => 1
    ];

    $this->plugin->filterFormAlter(
      $form,
      $form_state,
      $this->params + (array)$this->userData->get('murmurations', $this->uid, 'pref')
    );

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
      '#weight' => 10
    ];

    if ($this->params) {
      $curr_user = User::load($this->uid);
      $this->params += murmurations_geolocate_entity_with_fallback($curr_user);
      [$items, $metadata] = $this->searchRequest();
      if ($metadata and $metadata->number_of_results) {
        if (count($items) == $metadata->number_of_results) {
          $title = $this->t('Showing all results');
        }
        else {
          $title = $this->t('Showing @count results of @total', ['@count' => count($items), '@total' => $metadata->number_of_results]);
        }
        $form['results'] = [
          '#title' => $title,
          '#type' => 'fieldset',
          '#open' => TRUE,
          '#weight' => 12
        ];
        $form['results']['items'] = $this->showResults($items, $metadata->number_of_results);
      }
      else {
        $form['results'] = ['#markup' => Markup::create($this->t('No results.'))];
      }
    }

    $form['#attached']['library'][] = 'murmurations/filter_form';
    return $form;
  }

  /**
   * {@inheritDoc}
   */
  function submitForm(array &$form, FormStateInterface $form_state) {
    foreach ($this->plugin->filterFormValues($form_state->cleanValues()->getvalues()) as $key => $val) {
      $filters[$key] = $val;
    }
    $filters['page_size'] = static::RESULTS_PER_PAGE;
    if ($range = $form_state->getValue('range')) {
      $filters['range'] = $range;
      // All searches should be centred around a point.
      $filters += $this->getFallbackCoords();
    }
    if ($fragment = $form_state->getValue('fragment')) {
      $filters['text'] = $fragment;
    }
    $form_state->setRedirect(
      $this->routeMatch->getRouteName(),
      [],
      [
        'query' => array_filter($filters)
      ]
    );
    // Remember the user settings.
    $this->userData->set('murmurations', $this->uid, 'range', $range);
  }

  /**
   * Get the centre of the search, the user's position or the site position.
   * @return array
   *   with float 'lat' and float 'lon'
   */
  function getFallbackCoords() : array {
    return \Drupal::config('murmurations.settings')->get('fallback_point');
  }

  /**
   * Submit to the search engine and parse the results a bit
   *
   * @staticvar array $result
   *
   * @return array
   *   the results array and metadata array.
   */
  protected function searchRequest() : array {
    static $result;
    if (!isset($result)) {
      $options['headers'] = [
        'Accept' => 'application/json',
      ];
      $url = $this->aggregator .'?'. http_build_query($this->params);
      try {
        $response = \Drupal::service('http_client')->get($url, $options);
      }
      catch(\Exception $e) {
        trigger_error($e->getMessage(), E_USER_ERROR);
        $response = new Response($e->getCode(), [], NULL, '1.1', $e->getMessage());
      }

      if ($response->getStatusCode() != 200) {
        \Drupal::messenger()->addStatus($response->getReasonPhrase());
        $result = [NULL, NULL];
      }
      elseif ($contents = json_decode($response->getBody()->getContents())) {
        $result = [(array)$contents->data, $contents->meta];
      }
    }
    return $result;
  }

  abstract public function showResults(array $results, int $number_of_results) :array;

}

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

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