You are here

public function BynderSearch::getForm in Bynder 8.2

Same name and namespace in other branches
  1. 8.3 src/Plugin/EntityBrowser/Widget/BynderSearch.php \Drupal\bynder\Plugin\EntityBrowser\Widget\BynderSearch::getForm()
  2. 8 src/Plugin/EntityBrowser/Widget/BynderSearch.php \Drupal\bynder\Plugin\EntityBrowser\Widget\BynderSearch::getForm()
  3. 4.0.x src/Plugin/EntityBrowser/Widget/BynderSearch.php \Drupal\bynder\Plugin\EntityBrowser\Widget\BynderSearch::getForm()

Overrides BynderWidgetBase::getForm

File

src/Plugin/EntityBrowser/Widget/BynderSearch.php, line 282

Class

BynderSearch
Uses a Bynder API to search and provide entity listing in a browser's widget.

Namespace

Drupal\bynder\Plugin\EntityBrowser\Widget

Code

public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) {
  $form = parent::getForm($original_form, $form_state, $additional_widget_parameters);
  if ($form_state
    ->getValue('errors')) {
    $form['actions']['submit']['#access'] = FALSE;
    return $form;
  }
  $form['#attached']['library'][] = 'bynder/search_view';
  $form['filters'] = [
    '#type' => 'container',
    '#tree' => TRUE,
    '#attributes' => [
      'class' => 'bynder-filters',
    ],
  ];
  $form['filters']['search_bynder'] = [
    '#type' => 'textfield',
    '#weight' => -1,
    '#title' => $this
      ->t('Search keyword'),
    '#attributes' => [
      'size' => 30,
    ],
  ];
  if ($this->configuration['tags_filter']) {
    try {

      /*
       * Warning: update caching config if changing this API call.
       *
       * @see \Drupal\bynder\BynderApi::AUTO_UPDATED_TAGS_QUERIES
       * @see \Drupal\bynder\BynderApi::getTags().
       */
      $all_tags = array_map(function ($item) {
        return $item['tag'];
      }, $this->bynderApi
        ->getTags([
        'limit' => 500,
        'orderBy' => 'mediaCount desc',
        'minCount' => 1,
      ]));
      $tags = array_combine($all_tags, $all_tags);
      asort($tags);
    } catch (\Exception $e) {
      watchdog_exception('bynder', $e);
      (new UnableToConnectException())
        ->displayMessage();
      $form['actions']['submit']['#access'] = FALSE;
      $form['filters']['#access'] = FALSE;
      return $form;
    }
    if (\Drupal::service('module_handler')
      ->moduleExists('bynder_select2')) {
      $form['filters']['tags'] = [
        '#type' => 'bynder_select2_simple_element',
        '#multiple' => TRUE,
        '#title' => $this
          ->t('Tags'),
        '#options' => $tags,
        '#placeholder_text' => t('Search for a tag'),
      ];
    }
    else {
      $form['filters']['tags'] = [
        '#type' => 'select',
        '#multiple' => TRUE,
        '#title' => $this
          ->t('Tags'),
        '#options' => $tags,
      ];
    }
  }
  $max_option_weight = 0;
  try {
    $meta_properties = $this->bynderApi
      ->getMetaproperties();
  } catch (\Exception $e) {
    watchdog_exception('bynder', $e);
    (new UnableToConnectException())
      ->displayMessage();
    $form['actions']['submit']['#access'] = FALSE;
    $form['filters']['#access'] = FALSE;
    return $form;
  }
  foreach ($this->configuration['allowed_properties'] as $key) {

    // Don't display filter that is not filterable and has no options.
    if (in_array($key, array_keys($meta_properties)) && ($option = $meta_properties[$key]) && $option['isFilterable']) {
      $form['filters'][$option['name']] = [
        '#title' => bynder_get_applicable_label_translation($option),
        '#type' => 'select',
        '#multiple' => $option['isMultiselect'] ? TRUE : FALSE,
        '#required' => $option['isRequired'] ? TRUE : FALSE,
        '#weight' => $option['zindex'],
        '#empty_option' => $this
          ->t('- None -'),
        '#parents' => [
          'filters',
          'meta_properties',
          $option['name'],
        ],
      ];
      foreach ($option['options'] as $value) {
        $form['filters'][$option['name']]['#options'][$value['id']] = bynder_get_applicable_label_translation($value);
      }

      // Get the biggest weight from our filters so we position the other
      // elements after them.
      $max_option_weight = max($max_option_weight, $option['zindex']);
    }
  }
  $form['search_button'] = [
    '#type' => 'button',
    '#weight' => $max_option_weight + 10,
    '#value' => $this
      ->t('Search'),
    '#name' => 'search_submit',
    // Limit validation to the filter elements only.
    '#limit_validation_errors' => [
      [
        'filters',
      ],
    ],
  ];
  $form['thumbnails'] = [
    '#type' => 'container',
    '#weight' => $max_option_weight + 15,
    '#attributes' => [
      'id' => 'thumbnails',
      'class' => 'grid',
    ],
  ];
  if ($form_state
    ->getTriggeringElement()['#name'] == 'search_submit') {
    EntityBrowserPagerElement::setCurrentPage($form_state);
  }
  $page = EntityBrowserPagerElement::getCurrentPage($form_state);
  $query = [
    'limit' => $this->configuration['items_per_page'],
    'page' => $page,
    'type' => 'image',
    'total' => 1,
  ];
  if ($form_state
    ->getValue([
    'filters',
    'search_bynder',
  ])) {
    $query['keyword'] = $form_state
      ->getValue([
      'filters',
      'search_bynder',
    ]);
  }
  foreach ($form_state
    ->getValue([
    'filters',
    'meta_properties',
  ], []) as $key => $option_id) {
    if (is_array($option_id) && $option_id) {
      $property_ids = implode(',', $option_id);
      $query['property_' . $key] = $property_ids;
    }
    elseif (is_string($option_id) && $option_id) {
      $property_ids = $option_id;
      $query['property_' . $key] = $property_ids;
    }
  }
  if ($selected_tags = $form_state
    ->getValue([
    'filters',
    'tags',
  ])) {
    $selected_tags = array_values($selected_tags);
    $query['tags'] = implode(',', $selected_tags);
  }

  // Allow modules to alter the query.
  $this->moduleHandler
    ->alter('bynder_search_query', $query, $form_state, $this);
  try {

    // We store last result into the form state to prevent same requests
    // happening multiple times if not necessary.
    if (!empty($form_state
      ->get('bynder_media_list_hash')) && $form_state
      ->get('bynder_media_list_hash') == md5(implode('', $query))) {
      $media_list = $form_state
        ->get('bynder_media_list');
    }
    else {
      $media_list = $this->bynderApi
        ->getMediaList($query);

      // Set the Bynder ID as the array key.
      $media_list['media'] = array_combine(array_map(function ($media) {
        return $media['id'];
      }, $media_list['media']), array_values($media_list['media']));
      $form_state
        ->set('bynder_media_list', $media_list);
      $form_state
        ->set('bynder_media_list_hash', md5(implode('', $query)));
    }
  } catch (\Exception $e) {
    watchdog_exception('bynder', $e);
    (new UnableToConnectException())
      ->displayMessage();
    $form['actions']['submit']['#access'] = FALSE;
    $form['filters']['#access'] = FALSE;
    return $form;
  }
  if (!empty($media_list['media'])) {
    foreach ($media_list['media'] as $id => $media) {
      $form['thumbnails']["thumbnail-{$id}"] = [
        '#type' => 'container',
        '#attributes' => [
          'id' => $id,
          'class' => [
            'grid-item',
          ],
        ],
      ];
      $form['thumbnails']["thumbnail-{$id}"]["check_{$id}"] = [
        '#type' => 'checkbox',
        '#parents' => [
          'selection',
          $id,
        ],
        '#attributes' => [
          'class' => [
            'item-selector',
          ],
        ],
      ];
      $form['thumbnails']["thumbnail-{$id}"]['image'] = [
        '#theme' => 'bynder_search_item',
        '#thumbnail_uri' => $media['thumbnails']['thul'],
        '#name' => $media['name'],
        '#type' => $media['type'],
      ];
    }
    $form['pager_eb'] = [
      '#type' => 'entity_browser_pager',
      '#total_pages' => (int) ceil($media_list['total']['count'] / $this->configuration['items_per_page']),
      '#weight' => $max_option_weight + 15,
    ];

    // Set validation errors limit to prevent validation of filters on select.
    // We also need to set #submit to the default submit callback otherwise
    // limit won't take effect. Thank you Form API, you are very kind...
    // @see \Drupal\Core\Form\FormValidator::determineLimitValidationErrors()
    $form['actions']['submit']['#limit_validation_errors'] = [
      [
        'selection',
      ],
      [
        'widget',
      ],
    ];
    $form['actions']['submit']['#submit'] = [
      '::submitForm',
    ];
  }
  else {
    $form['empty_message'] = [
      '#prefix' => '<div class="empty-message">',
      '#markup' => $this
        ->t('Not assets found for current search criteria.'),
      '#suffix' => '</div>',
      '#weight' => $max_option_weight + 20,
    ];
    $form['actions']['submit']['#access'] = FALSE;
  }
  return $form;
}